<?php

namespace App\Modules\Addon\MigrateWisecp\Importers;

use App\Models\Client;
use App\Models\Invoice;
use App\Models\InvoiceItem;
use App\Modules\Addon\MigrateWisecp\Services\WisecpSourceConnection;
use Illuminate\Support\Facades\DB;

/**
 * PRC-1125 — WiseCP `invoices` → procp `Invoice` (+ `invoices_items` → `InvoiceItem`).
 *
 * WiseCP FARKLARI:
 * - Kalemler `invoices_items`.**`owner_id`** ile bağlanır (= invoice id; `parent_id`
 *   gerçek veride 0'dır — WiseCP konvansiyonu, tickets_replies.owner_id gibi).
 * - `number` '#1' formatında → kanonik 'WISECP-1' üretilir.
 * - currency int → wisecp_currency_map → procp; yoksa client currency.
 * - status 'ghost' (taslak) → pending. Ödeme/transaction satırları göç ETMEZ (kapsam
 *   dışı — yalnız fatura + kalemler; datepaid varsa paid_date doldurulur).
 */
class InvoiceImporter extends AbstractWisecpImporter
{
    public function sourceType(): string
    {
        return 'invoice';
    }

    protected function sourceTable(): string
    {
        return 'invoices';
    }

    protected function importRow(object $row): ?int
    {
        $clientId = $this->ledger->map('client', $row->user_id);
        if ($clientId === null) {
            $this->report->warn(
                $this->sourceType(),
                "Fatura #{$row->id}: client (user_id={$row->user_id}) import edilmemiş → atlandı."
            );

            return null;
        }

        $currencyId = $this->resolveCurrencyId($row->currency ?? null, (int) $clientId);
        $status = $this->mapStatus($row->status ?? null);
        $paidDate = $this->normalizeDate($row->datepaid ?? null);

        $number = ltrim(trim((string) ($row->number ?? $row->id)), '#');
        $invoiceNumber = 'WISECP-'.($number !== '' ? $number : $row->id);

        $invoice = Invoice::create([
            'client_id' => $clientId,
            'currency_id' => $currencyId,
            'invoice_number' => $invoiceNumber,
            'status' => $status,
            'subtotal' => $row->subtotal ?? 0,
            'tax_amount' => $row->tax ?? 0,
            'tax_rate' => $row->taxrate ?? 0,
            'total_amount' => $row->total ?? 0,
            'payment_method' => ($row->pmethod ?? '') !== '' && $row->pmethod !== 'none' ? $row->pmethod : null,
            'notes' => ($row->notes ?? '') !== '' ? $row->notes : null,
            'issued_at' => $this->normalizeDate($row->cdate ?? null),
            'due_date' => $this->normalizeDate($row->duedate ?? null),
            'paid_date' => $status === Invoice::STATUS_PAID ? $paidDate : null,
        ]);

        $this->importItems((int) $row->id, $invoice->id);

        return $invoice->id;
    }

    /** İlgili `invoices_items` (parent_id) satırlarını taşı. */
    protected function importItems(int $wisecpInvoiceId, int $procpInvoiceId): void
    {
        $items = WisecpSourceConnection::table('invoices_items')
            ->where('owner_id', $wisecpInvoiceId)
            ->orderBy('rank')
            ->orderBy('id')
            ->get();

        $sortOrder = 0;

        foreach ($items as $item) {
            $amount = $item->total_amount ?? ($item->amount ?? 0);
            $qty = (int) ($item->quantity ?? 1) ?: 1;

            InvoiceItem::create([
                'invoice_id' => $procpInvoiceId,
                'sort_order' => $sortOrder++,
                'description' => (string) ($item->description ?? ''),
                'quantity' => $qty,
                'unit_price' => $qty > 0 ? ($amount / $qty) : $amount,
                'total' => $amount,
                'line_total' => $amount,
            ]);
        }
    }

    protected function resolveCurrencyId(mixed $wisecpCurrencyId, int $clientId): ?int
    {
        $wid = (int) $wisecpCurrencyId;
        if ($wid > 0) {
            $mapped = DB::table('wisecp_currency_map')->where('wisecp_currency_id', $wid)->value('procp_currency_id');
            if ($mapped) {
                return (int) $mapped;
            }
        }

        return Client::whereKey($clientId)->value('currency_id');
    }

    /** WiseCP invoice status → procp Invoice::STATUS_*. Bilinmeyen/ghost → pending/unpaid. */
    protected function mapStatus(?string $status): string
    {
        return match (strtolower(trim((string) $status))) {
            'paid' => Invoice::STATUS_PAID,
            'cancelled', 'canceled' => Invoice::STATUS_CANCELLED,
            'refunded' => Invoice::STATUS_REFUNDED,
            'ghost', 'draft' => Invoice::STATUS_PENDING,
            'collections', 'overdue' => Invoice::STATUS_OVERDUE,
            default => Invoice::STATUS_UNPAID,
        };
    }

    protected function normalizeDate(?string $value): ?string
    {
        $v = trim((string) $value);
        if ($v === '' || str_starts_with($v, '0000-00-00') || str_starts_with($v, '1881-05-19')) {
            return null;
        }

        return $v;
    }
}
