<?php

declare(strict_types=1);

namespace ABS\Modules\SalvageCenter\Repositories;

use PDO;
use RuntimeException;

final class SalvageCenterRepository
{
    private PDO $pdo;

    public function __construct()
    {
        $this->pdo = $this->resolvePdo();
    }

    public function all(): array
    {
        $sql = "SELECT v.*,
                       COALESCE(SUM(CASE WHEN p.status <> 'discarded' THEN p.estimated_price ELSE 0 END),0) AS parts_estimated,
                       COALESCE(SUM(CASE WHEN p.status = 'sold' THEN p.sale_price ELSE 0 END),0) AS sold_total,
                       COUNT(p.id) AS parts_count
                FROM dismantling_vehicles v
                LEFT JOIN dismantling_parts p ON p.vehicle_id = v.id
                GROUP BY v.id
                ORDER BY v.created_at DESC";
        return $this->pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }

    public function find(int $id): ?array
    {
        $st = $this->pdo->prepare('SELECT * FROM dismantling_vehicles WHERE id = ?');
        $st->execute([$id]);
        $row = $st->fetch(PDO::FETCH_ASSOC);
        return $row ?: null;
    }

    public function parts(int $vehicleId): array
    {
        $st = $this->pdo->prepare('SELECT * FROM dismantling_parts WHERE vehicle_id = ? ORDER BY category, name');
        $st->execute([$vehicleId]);
        return $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }

    public function create(array $d): int
    {
        $sql = "INSERT INTO dismantling_vehicles
        (vin, brand, model, production_month, production_year, engine, engine_code, power_hp, emission_standard,
         gearbox, mileage, color, color_code, damage_area, source, purchase_price, transport_cost, documents_cost,
         dismantling_cost, other_costs, desired_profit, status, notes, created_at, updated_at)
        VALUES
        (:vin,:brand,:model,:production_month,:production_year,:engine,:engine_code,:power_hp,:emission_standard,
         :gearbox,:mileage,:color,:color_code,:damage_area,:source,:purchase_price,:transport_cost,:documents_cost,
         :dismantling_cost,:other_costs,:desired_profit,'evaluation',:notes,NOW(),NOW())";
        $st=$this->pdo->prepare($sql);
        $st->execute($d);
        return (int)$this->pdo->lastInsertId();
    }

    public function seedParts(int $vehicleId): void
    {
        $templates = [
            ['Motor','Motor complet',6500,85],['Motor','Injectoare - set',1800,85],['Motor','Turbina',900,80],
            ['Motor','Pompa inalta presiune',900,70],['Motor','Alternator',350,80],['Motor','Electromotor',300,80],
            ['Motor','Compresor AC',500,70],['Motor','ECU motor',650,70],['Evacuare','DPF',1200,65],
            ['Evacuare','Catalizator',1300,75],['Transmisie','Cutie viteze',1800,75],['Transmisie','Volanta + ambreiaj',700,55],
            ['Caroserie','Far stanga',600,85],['Caroserie','Far dreapta',600,85],['Caroserie','Stop stanga',300,75],
            ['Caroserie','Stop dreapta',300,75],['Caroserie','Capota',600,60],['Caroserie','Bara fata',500,65],
            ['Caroserie','Bara spate',450,60],['Caroserie','Usa fata stanga',500,55],['Caroserie','Usa fata dreapta',500,55],
            ['Interior','Volan',350,70],['Interior','Airbag volan',500,65],['Interior','Airbag pasager',450,55],
            ['Interior','Ceasuri bord',350,65],['Interior','Radio / navigatie',450,70],['Rulare','Caseta directie',700,65],
            ['Rulare','Jante - set',1200,80],['Electrica','Calculator ABS',450,60],['Electrica','UCH / BCM',550,60]
        ];
        $st=$this->pdo->prepare("INSERT INTO dismantling_parts
            (vehicle_id,category,name,condition_status,tested,estimated_price,sale_probability,status,created_at,updated_at)
            VALUES (?,?,?,?,0,?,?,'available',NOW(),NOW())");
        foreach($templates as $t){ $st->execute([$vehicleId,$t[0],$t[1],'needs_test',$t[2],$t[3]]); }
    }

    public function saveParts(int $vehicleId, array $parts): void
    {
        $sql="UPDATE dismantling_parts SET condition_status=:condition_status,tested=:tested,oe_code=:oe_code,
             manufacturer_code=:manufacturer_code,estimated_price=:estimated_price,quick_sale_price=:quick_sale_price,
             sale_probability=:sale_probability,preparation_cost=:preparation_cost,status=:status,sale_price=:sale_price,
             location=:location,notes=:notes,updated_at=NOW() WHERE id=:id AND vehicle_id=:vehicle_id";
        $st=$this->pdo->prepare($sql);
        foreach($parts as $id=>$p){
            $st->execute([
                ':condition_status'=>$p['condition_status']??'needs_test', ':tested'=>isset($p['tested'])?1:0,
                ':oe_code'=>trim((string)($p['oe_code']??'')), ':manufacturer_code'=>trim((string)($p['manufacturer_code']??'')),
                ':estimated_price'=>(float)($p['estimated_price']??0), ':quick_sale_price'=>(float)($p['quick_sale_price']??0),
                ':sale_probability'=>(int)($p['sale_probability']??50), ':preparation_cost'=>(float)($p['preparation_cost']??0),
                ':status'=>$p['status']??'available', ':sale_price'=>(float)($p['sale_price']??0),
                ':location'=>trim((string)($p['location']??'')), ':notes'=>trim((string)($p['notes']??'')),
                ':id'=>(int)$id, ':vehicle_id'=>$vehicleId
            ]);
        }
    }

    public function updateStatus(int $id,string $status): void
    {
        $allowed=['evaluation','purchased','dismantling','active','closed'];
        if(!in_array($status,$allowed,true)){$status='evaluation';}
        $st=$this->pdo->prepare('UPDATE dismantling_vehicles SET status=?,updated_at=NOW() WHERE id=?');
        $st->execute([$status,$id]);
    }

    public function delete(int $id): void
    {
        $this->pdo->beginTransaction();
        try {
            $this->pdo->prepare('DELETE FROM dismantling_parts WHERE vehicle_id=?')->execute([$id]);
            $this->pdo->prepare('DELETE FROM dismantling_vehicles WHERE id=?')->execute([$id]);
            $this->pdo->commit();
        } catch (\Throwable $e) { $this->pdo->rollBack(); throw $e; }
    }

    private function resolvePdo(): PDO
    {
        $classes=['ABS\\Core\\Database','ABS\\Database\\Database','App\\Core\\Database'];
        foreach($classes as $class){
            if(!class_exists($class)) continue;
            foreach(['connection','getConnection','pdo','getInstance','instance'] as $method){
                if(!method_exists($class,$method)) continue;
                try {
                    $value=$class::$method();
                    if($value instanceof PDO) return $value;
                    if(is_object($value)){
                        foreach(['connection','getConnection','pdo'] as $m){
                            if(method_exists($value,$m)){ $p=$value->$m(); if($p instanceof PDO) return $p; }
                        }
                    }
                } catch (\Throwable $e) {}
            }
        }
        if(isset($GLOBALS['pdo']) && $GLOBALS['pdo'] instanceof PDO) return $GLOBALS['pdo'];
        throw new RuntimeException('Conexiunea PDO ABS nu a putut fi identificata. Verifica configurarea bazei de date.');
    }
}
