<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

/**
 * Maps a cr6f2_documentses record (with expanded crf61_invoicemapping
 * and cr6f2_journalentrymapping) to the API response shape.
 */
class DocumentResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        // Invoice data merged in by InvoiceController::index() two-query approach
        $inv = $this['_invoice']                   ?? [];
        $je  = $this['cr6f2_journalentrymapping']  ?? [];
        $errors = $this->parseErrors($this['cr6f2_errorsjson'] ?? null);

        return [
            // ── Document fields ──────────────────────────────────────
            'id'               => $this['cr6f2_documentsid'],
            'doc_name'         => $this['cr6f2_documentname']                                               ?? null,
            'main_doc_type'    => $this['cr6f2_maindoctype']                                                ?? null,
            'ocr_status'       => $this['cr6f2_ocrstatus']                                                  ?? null,
            'ocr_status_label' => $this->ocrStatusLabel($this['cr6f2_ocrstatus'] ?? null),
            'upload_date'      => $this['cr6f2_uploadeddate']                                               ?? null,
            'autocount_docno'  => $this['cr6f2_autocountnumber']                                            ?? null,
            'autocount_number' => $this['cr6f2_autocountnumber']                                            ?? null,
            'excel_link'       => $this['cr6f2_exporttoexcellink']                                          ?? null,
            'exported_excel'   => $this['cr6f2_exporttoexcel']                                              ?? false,
            'exported_ac'      => $this['cr6f2_exporttoautocount']                                          ?? false,
            'uploaded_by_name' => $this['_cr6f2_uploadedbyappuser_value@OData.Community.Display.V1.FormattedValue'] ?? $this['_cr6f2_uploadedby_value@OData.Community.Display.V1.FormattedValue'] ?? null,
            'company_id'       => $this['_cr6f2_companyid_value']                                           ?? null,
            'review_comment'   => $this['cr6f2_reviewcomment']                                              ?? null,
            'reject_reason'    => $this['cr6f2_rejectreason']                                              ?? null,
            'rejected_on'      => $this['cr6f2_rejectedon']                                                ?? null,
            'rejected_by'      => $this['_cr6f2_rejectedbyappuser_value'] ?? $this['_cr6f2_rejectedby_value']                                         ?? null,
            'rejected_by_name' => $this['_cr6f2_rejectedbyappuser_value@OData.Community.Display.V1.FormattedValue'] ?? $this['_cr6f2_rejectedby_value@OData.Community.Display.V1.FormattedValue'] ?? null,
            'deleted_on'       => $this['cr6f2_deletedon']                                                 ?? null,
            'deleted_by'       => $this['_cr6f2_deletedbyappuser_value'] ?? $this['_cr6f2_deletedby_value']                                          ?? null,
            'deleted_by_name'  => $this['_cr6f2_deletedbyappuser_value@OData.Community.Display.V1.FormattedValue'] ?? $this['_cr6f2_deletedby_value@OData.Community.Display.V1.FormattedValue']  ?? null,
            'label'            => $this['crf61_label']                                                     ?? null,
            'manual_split'          => (bool) ($this['cr6f2_manualsplit']          ?? false),
            'ac_duplicate_warning'  => (bool) ($this['cr6f2_acduplicatewarning']  ?? false),
            'store_move_warning'    => $this['cr6f2_storemovewarning']            ?? null,
            // SCRUM-88 — unified user-facing issue store (stacked, plain-language).
            'has_error'             => (bool) ($this['cr6f2_haserror'] ?? false),
            'errors'                => $errors,
            'error_severity'        => $this->maxSeverity($errors),
            'remark'           => $this['cr6f2_remark']                                                    ?? null,
            'document_link'    => $this->utf8Safe($this['cr6f2_documentlink']    ?? null),
            'stored_link'      => $this->utf8Safe($this['cr6f2_documentstoredlink'] ?? null),
            'is_active'        => ($this['statecode'] ?? 1) === 0,
            'created_at'       => $this['createdon']                                                        ?? null,
            'modified_at'      => $this['modifiedon']                                                       ?? null,

            // ── Invoice fields (merged from cr6f2_invoices two-query) ────
            'invoice_id'       => $inv['cr6f2_invoiceid']              ?? null,
            'invoice_number'   => $inv['cr6f2_invoicenumber']          ?? null,
            'date'             => $inv['cr6f2_date']                    ?? null,
            'total_amount'     => $inv['cr6f2_totalamount']            ?? null,
            // Cashbook: payment-method's account currency (set in index()); else the vendor draft.
            'currency'         => $inv['_pm_currency'] ?? $inv['cr6f2_vendorcurrecycodedraft'] ?? null,
            'vendor_name'        => $inv['cr6f2_vendornamedraft']        ?? null,
            'vendor_address'     => $inv['cr6f2_vendoraddressdraft']     ?? null,
            'vendor_id'          => $inv['_cr6f2_debtorcreditormapping_value'] ?? null,
            'mapped_vendor_name' => ($inv['_vendor']['cr6f2_debtorcreditorcompanyname'] ?? null),
            'mapped_vendor_code' => ($inv['_vendor']['cr6f2_debtorcreditorcode']        ?? null),
            'doc_type'              => $inv['cr6f2_docuementtype'] ?? null,
            'doc_type_label'        => $inv['cr6f2_docuementtype@OData.Community.Display.V1.FormattedValue'] ?? null,
            'credit_note'           => $inv['cr6f2_creditnotenumber']       ?? null,
            'description'           => $inv['cr6f2_description']            ?? null,
            'currency_rate'         => $inv['cr6f2_currencyrate']           ?? null,
            'credit_term'           => $inv['cr6f2_credittermchoice']       ?? null,
            'reason'                => $inv['cr6f2_reason']                 ?? null,
            'summary_mode'          => $inv['cr6f2_summarymode']            ?? false,
            'tax_inclusive'         => (bool) ($inv['cr6f2_taxinclusive']  ?? false),
            'purchase_location_id'  => $inv['_cr6f2_purchaselocation_value'] ?? null,
            'purchase_location_name'=> $inv['_cr6f2_purchaselocation_value@OData.Community.Display.V1.FormattedValue'] ?? null,
            'bank_charge'           => $inv['crf61_bankcharge']               ?? null,
            'bc_proj_no_id'         => $inv['_cr6f2_bankchargeprojno_value']  ?? null,
            'bc_proj_no_code'       => $inv['_cr6f2_bankchargeprojno_value@OData.Community.Display.V1.FormattedValue'] ?? null,
            'proj_no_id'            => $inv['_cr6f2_masterprojno_value']      ?? null,
            'proj_no_code'          => $inv['_cr6f2_masterprojno_value@OData.Community.Display.V1.FormattedValue'] ?? null,
            'payment_method_id'     => $inv['_crf61_paymentmethodmapping_value'] ?? null,
            'payment_method_name'   => $inv['_crf61_paymentmethodmapping_value@OData.Community.Display.V1.FormattedValue'] ?? null,
            'doc_no_format_id'      => $inv['_cr6f2_docnoformatmapping_value'] ?? null,
            'doc_no_format_name'    => $inv['_cr6f2_docnoformatmapping_value@OData.Community.Display.V1.FormattedValue'] ?? null,
            'daily_account_folder'  => $this['cr6f2_dailyaccountfolder'] ?? null,

            // ── Extended cash/payment fields (8 desktop types) ────────────
            'party_id'              => $inv['_cr6f2_debtorcreditormapping_value'] ?? null,
            'party_code'            => null,
            'party_name'            => null,
            'deposit_account'       => $inv['cr6f2_depositaccount'] ?? null,
            'cheque_no'             => $inv['cr6f2_chequeno'] ?? null,
            'knockoffs'             => $this->parseKnockoffs($inv['cr6f2_knockoffsjson'] ?? null),

            // ── JE fields (from cr6f2_journalentrymapping expand) ────
            'je_id'            => $je['cr6f2_journalentryid'] ?? null,
            'je_name'          => $je['cr6f2_journalentryname']     ?? null,
            'je_date'          => $je['cr6f2_docdate']              ?? $je['cr6f2_date'] ?? null,
            'je_amount'        => $je['cr6f2_totalamount']          ?? $je['cr6f2_totaldebit']  ?? null,
        ];
    }

    private function utf8Safe(?string $v): ?string
    {
        return $v === null ? null : mb_convert_encoding($v, 'UTF-8', 'UTF-8');
    }

    /** Decode the cr6f2_knockoffsjson memo into an array; [] if empty/invalid. */
    private function parseKnockoffs(?string $json): array
    {
        if ($json === null || $json === '') return [];
        $decoded = json_decode($json, true);
        return is_array($decoded) ? $decoded : [];
    }

    /** Decode cr6f2_errorsjson into a normalised list of {stage, severity, message, at}. */
    private function parseErrors(?string $json): array
    {
        if ($json === null || $json === '') return [];
        $decoded = json_decode($json, true);
        if (!is_array($decoded)) return [];
        return array_values(array_filter(array_map(
            fn($i) => is_array($i) ? array_filter([
                'stage'    => $i['stage']    ?? null,
                'severity' => $i['severity'] ?? 'warning',
                'message'  => $i['message']  ?? '',
                'detail'   => $i['detail']   ?? null,
                'at'       => $i['at']       ?? null,
            ], fn($v) => $v !== null) : null,
            $decoded,
        )));
    }

    /** Highest severity across the issue list: 'error' beats 'warning'; null if empty. */
    private function maxSeverity(array $errors): ?string
    {
        if ($errors === []) return null;
        foreach ($errors as $e) {
            if (($e['severity'] ?? '') === 'error') return 'error';
        }
        return 'warning';
    }

    private function ocrStatusLabel(?int $status): string
    {
        // cr6f2_Documents.cr6f2_ocrstatus values
        return match ($status) {
            521880000 => 'Draft',
            521880001 => 'Pending Review',
            521880002 => 'Completed',
            521880003 => 'Pending Move',
            521880004 => 'Stored',
            521880005 => 'Rejected',
            521880006 => 'Error',
            521880007 => 'Pending Import',
            521880008 => 'Deleted',
            default   => 'Unknown',
        };
    }
}
