<?php

namespace App\Services\Minimax;

use App\Models\Contract;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;

class MinimaxInvoiceService
{
    public function __construct(private MinimaxClient $client) {}

    /**
     * Fetch issued invoices with filters.
     * Old app: GET /api/api/orgs/{orgId}/issuedinvoices/?{filters}
     */
    public function getIssuedInvoices(string $account, array $filters = []): array
    {
        $response = $this->client->get($account, 'issuedinvoices/', array_filter($filters));
        $response->throw();
        return $response->json();
    }

    /**
     * Fetch single invoice with customer and country info.
     * Old app: getIssuedInvoiceAllData
     */
    public function getIssuedInvoiceAllData(string $account, int $issuedInvoiceId): array
    {
        $response = $this->client->get($account, "issuedinvoices/{$issuedInvoiceId}");
        $response->throw();
        $invoice = $response->json();

        // Fetch customer info via ResourceUrl
        if (!empty($invoice['Customer']['ResourceUrl'])) {
            $invoice['customerInfo'] = $this->getDataByResourceUrl($account, $invoice['Customer']['ResourceUrl']);
        }

        // Fetch country info via ResourceUrl
        if (!empty($invoice['AddresseeCountry']['ResourceUrl'])) {
            $invoice['customerInfo']['countryInfo'] = $this->getDataByResourceUrl($account, $invoice['AddresseeCountry']['ResourceUrl']);
        }

        return $invoice;
    }

    /**
     * Fetch customer by ID.
     * Old app: GET /api/api/orgs/{orgId}/customers/{customerId}
     */
    public function getCustomerById(string $account, int $customerId): array
    {
        $response = $this->client->get($account, "customers/{$customerId}");
        $response->throw();
        return $response->json();
    }

    /**
     * Fetch organizations.
     * Old app: GET /api/api/currentuser/orgs
     */
    public function getOrganizations(string $account): array
    {
        $token = app(MinimaxAuthService::class)->getToken($account);
        $baseUrl = rtrim(config("minimax.accounts.{$account}.url"), '/');
        $url = "{$baseUrl}/api/api/currentuser/orgs";

        $response = Http::withToken($token)->acceptJson()->get($url);
        $response->throw();
        return $response->json();
    }

    /**
     * Create a new issued invoice.
     * Old app: POST /api/api/orgs/{orgId}/issuedinvoices/
     */
    public function addIssuedInvoice(string $account, array $invoiceData): array
    {
        $response = $this->client->post($account, 'issuedinvoices/', $invoiceData);
        $response->throw();
        return $response->json();
    }

    /**
     * Fetch document attachment (PDF or XML).
     * Old app: GET /api/api/orgs/{orgId}/documents/{documentId}/attachments/{attachmentId}
     */
    public function getDocumentAttachment(string $account, int $documentId, int $attachmentId): array
    {
        $response = $this->client->get($account, "documents/{$documentId}/attachments/{$attachmentId}");
        $response->throw();
        return $response->json();
    }

    /**
     * Fetch data by Minimax ResourceUrl.
     * Old app: getDataByResourceUrl — appends /api prefix to ResourceUrl
     */
    private function getDataByResourceUrl(string $account, string $resourceUrl): array
    {
        $token = app(MinimaxAuthService::class)->getToken($account);
        $baseUrl = rtrim(config("minimax.accounts.{$account}.url"), '/');
        $url = "{$baseUrl}/api{$resourceUrl}";

        $response = Http::withToken($token)->acceptJson()->get($url);
        $response->throw();
        return $response->json();
    }

    /**
     * Build invoice payload from a Contract model.
     * Ported from old InOfficeInvoices::createInvoice()
     */
    public function buildInvoiceFromContract(string $account, Contract $contract): array
    {
        $templatePath = resource_path('minimax/newInvoice.json');
        if (!file_exists($templatePath)) {
            throw new \RuntimeException("Invoice template not found at {$templatePath}");
        }

        $invoice = json_decode(file_get_contents($templatePath), true);

        // Fetch customer info from Minimax
        $customer = $this->getCustomerById($account, $contract->customer_id);

        // Customer info
        $invoice['Customer']['ID'] = $contract->customer_id;
        $invoice['AddresseeName'] = $customer['Name'] ?? '';
        $invoice['AddresseeAddress'] = $customer['Address'] ?? '';
        $invoice['AddresseePostalCode'] = $customer['PostalCode'] ?? '';
        $invoice['AddresseeCity'] = $customer['City'] ?? '';

        if (!empty($customer['Country']['ID'])) {
            $invoice['AddresseeCountry']['ID'] = $customer['Country']['ID'];
        }

        // Document reference
        $invoice['DocumentReference'] = "Ugovor br." . $contract->contract_no;

        // Notes from napomena
        if (!empty($contract->napomena) && is_array($contract->napomena)) {
            $invoice['Notes'] = implode("\n", $contract->napomena);
        }

        // Description above
        if (!empty($contract->description_above)) {
            $invoice['DescriptionAbove'] = $contract->description_above;
        }

        // Dates — use startOfDay to avoid Minimax rounding 23:59:59 to next day
        $now = Carbon::now();
        $firstDay = $now->copy()->startOfMonth()->startOfDay();
        $lastDay = $now->copy()->endOfMonth()->startOfDay();
        $dueDate = $lastDay->copy()->addDays($contract->invoice_due_days);

        $invoice['DateIssued'] = $lastDay->format(DATE_W3C);
        $invoice['DateTransactionFrom'] = $firstDay->format(DATE_W3C);
        $invoice['DateTransaction'] = $lastDay->format(DATE_W3C);
        $invoice['DateDue'] = $dueDate->format(DATE_W3C);

        // Invoice description
        $descriptions = [
            'month' => "Održavanje web stranice {$contract->website}., sukladno ugovoru o održavanju br. {$contract->contract_no}. Za {$now->format('m/Y')}",
            'year' => "Održavanje web stranice {$contract->website}., sukladno ugovoru o održavanju br. {$contract->contract_no}. Za {$now->format('Y')}/" . ($now->format('Y') + 1),
        ];

        // Price
        $price = $contract->payment === 'month' ? (float) $contract->price_per_month : (float) $contract->price_per_year;
        $priceVat = $contract->payment === 'month' ? (float) $contract->price_per_month_vat : (float) $contract->price_per_year_vat;

        // Invoice row
        $invoice['IssuedInvoiceRows'][0]['ItemName'] = 'Održavanje web stranice';
        $invoice['IssuedInvoiceRows'][0]['Description'] = $descriptions[$contract->payment] ?? $descriptions['month'];
        $invoice['IssuedInvoiceRows'][0]['Price'] = $price;
        $invoice['IssuedInvoiceRows'][0]['PriceWithVAT'] = $priceVat;

        return $invoice;
    }
}
