<?php

namespace App\Services;

use App\Models\DocumentHeader;
use App\Models\SupplierDocumentHeader;
use App\Models\Receipt;
use App\Models\DocumentLink;
use App\Models\DocumentLineLink;
use App\Models\DocumentStatusHistory;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class DocumentLinkService
{
    /**
     * Get the normalized document type string.
     */
    public function getDocType(object $doc): string
    {
        if ($doc instanceof DocumentHeader || $doc instanceof SupplierDocumentHeader) {
            return $doc->type;
        }
        if ($doc instanceof Receipt) {
            return 'receipt';
        }
        if (isset($doc->type)) {
            return $doc->type;
        }
        return strtolower(class_basename($doc));
    }

    /**
     * Resolve the actual model instance based on ID and type.
     */
    public function resolveModel(int $id, string $type)
    {
        switch ($type) {
            case 'quotation':
            case 'sales_order':
            case 'invoice':
            case 'credit_note':
            case 'debit_note':
                return DocumentHeader::find($id);
            case 'purchase_order':
            case 'goods_received':
            case 'sales_invoice':
            case 'returns_debit':
            case 'credit_supplier':
                return SupplierDocumentHeader::find($id);
            case 'receipt':
                return Receipt::find($id);
            default:
                return null;
        }
    }

    /**
     * Create a link between a source and a target document.
     */
    public function link(object $source, object $target, string $linkType = 'converted_to'): DocumentLink
    {
        return DB::transaction(function () use ($source, $target, $linkType) {
            $sourceType = $this->getDocType($source);
            $targetType = $this->getDocType($target);

            // 1. Create or retrieve the DocumentLink
            $link = DocumentLink::firstOrCreate([
                'source_id'   => $source->id,
                'source_type' => $sourceType,
                'target_id'   => $target->id,
                'target_type' => $targetType,
            ], [
                'link_type'   => $linkType,
                'status'      => 'active',
                'created_by'  => Auth::id(),
            ]);

            // 2. Keep lightweight denormalized columns in sync
            if ($target instanceof DocumentHeader || $target instanceof SupplierDocumentHeader) {
                $target->update([
                    'parent_document_id'   => $source->id,
                    'parent_document_type' => $sourceType,
                ]);
            }

            // 3. Handle special Receipt-to-Invoice direct relationship
            if ($source instanceof Receipt && $target instanceof DocumentHeader && $targetType === 'invoice') {
                $source->update(['invoice_id' => $target->id]);
            } elseif ($target instanceof Receipt && $source instanceof DocumentHeader && $sourceType === 'invoice') {
                $target->update(['invoice_id' => $source->id]);
            }

            // 4. Update source status if appropriate (e.g. Quotation/PO/GRV converted)
            if ($linkType === 'converted_to') {
                if ($source instanceof DocumentHeader && $sourceType === 'quotation') {
                    $source->update(['status' => 'converted']);
                } elseif ($source instanceof SupplierDocumentHeader && in_array($sourceType, ['purchase_order', 'goods_received'])) {
                    $source->update(['status' => 'converted']);
                }
            }

            // 5. Add to document status history if table exists
            if (Schema::hasTable('document_status_history')) {
                if ($target instanceof DocumentHeader || $target instanceof SupplierDocumentHeader) {
                    DocumentStatusHistory::create([
                        'document_id'   => $target->id,
                        'document_type' => $targetType,
                        'from_status'   => null,
                        'to_status'     => $target->status ?? 'draft',
                        'action'        => $linkType,
                        'user_id'       => Auth::id(),
                        'notes'         => "Linked from {$sourceType} #{$source->id}",
                        'created_at'    => now(),
                    ]);
                }
            }

            return $link;
        });
    }

    /**
     * Prepare a line structure from a source line to be copied to a target.
     */
    public function prepareLineForTarget(object $sourceLine, object $target): array
    {
        $commonFields = [
            'module'             => $sourceLine->module ?? null,
            'hs_code'            => $sourceLine->hs_code ?? null,
            'item_id'            => $sourceLine->item_id ?? null,
            'account_id'         => $sourceLine->account_id ?? null,
            'account_type'       => $sourceLine->account_type ?? null,
            'warehouse_id'       => $sourceLine->warehouse_id ?? null,
            'quantity'           => $sourceLine->quantity ?? 0,
            'confirmed_quantity' => $sourceLine->confirmed_quantity ?? $sourceLine->quantity ?? 0,
            'uom_id'             => $sourceLine->uom_id ?? null,
            'price'              => $sourceLine->price ?? 0.0,
            'tax_id'             => $sourceLine->tax_id ?? null,
            'tax_rate'           => $sourceLine->tax_rate ?? 0.0,
            'discount_percent'   => $sourceLine->discount_percent ?? 0.0,
            'line_tax'           => $sourceLine->line_tax ?? 0.0,
            'line_total'         => $sourceLine->line_total ?? 0.0,
            'description'        => $sourceLine->description ?? null,
        ];

        if ($target instanceof DocumentHeader) {
            $commonFields['document_header_id'] = $target->id;
        } elseif ($target instanceof SupplierDocumentHeader) {
            $commonFields['supplier_document_header_id'] = $target->id;
        }

        return $commonFields;
    }

    /**
     * Get the source links for a given target document.
     */
    public function getLinkedFrom(int $targetId, string $targetType)
    {
        return DocumentLink::where('target_id', $targetId)
            ->where('target_type', $targetType)
            ->where('status', 'active')
            ->get();
    }

    /**
     * Get the target links for a given source document.
     */
    public function getLinkedTo(int $sourceId, string $sourceType)
    {
        return DocumentLink::where('source_id', $sourceId)
            ->where('source_type', $sourceType)
            ->where('status', 'active')
            ->get();
    }
}
