<?php

namespace App\Services;

use App\Models\Setting;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class WhmcsService
{
    protected string $apiUrl;
    protected string $identifier;
    protected string $secret;

    public function __construct()
    {
        $this->apiUrl = (string) Setting::getValue('whmcs', 'api_url', config('services.whmcs.url', ''));
        $this->identifier = (string) Setting::getValue('whmcs', 'api_identifier', config('services.whmcs.identifier', ''));
        $this->secret = (string) Setting::getValue('whmcs', 'api_secret', config('services.whmcs.secret', ''));
    }

    /**
     * Check if WHMCS is configured
     */
    public function isConfigured(): bool
    {
        return !empty($this->apiUrl) && !empty($this->identifier) && !empty($this->secret);
    }

    /**
     * Make API request to WHMCS
     */
    protected function makeRequest(string $action, array $params = []): array
    {
        if (!$this->isConfigured()) {
            return ['result' => 'error', 'message' => 'WHMCS is not configured'];
        }

        try {
            $response = Http::asForm()->post($this->apiUrl . '/includes/api.php', array_merge([
                'identifier' => $this->identifier,
                'secret' => $this->secret,
                'action' => $action,
                'responsetype' => 'json',
            ], $params));

            return $response->json() ?? ['result' => 'error', 'message' => 'Invalid response'];
        } catch (\Exception $e) {
            Log::error('WHMCS API Error: ' . $e->getMessage());
            return ['result' => 'error', 'message' => $e->getMessage()];
        }
    }

    /**
     * Test connection to WHMCS
     */
    public function testConnection(): array
    {
        $result = $this->makeRequest('GetAdminDetails');
        return [
            'success' => ($result['result'] ?? '') === 'success',
            'message' => $result['message'] ?? 'Connection successful',
        ];
    }

    /**
     * Get all clients from WHMCS
     */
    public function getClients(int $limitStart = 0, int $limitNum = 100): array
    {
        return $this->makeRequest('GetClients', [
            'limitstart' => $limitStart,
            'limitnum' => $limitNum,
        ]);
    }

    /**
     * Get client details
     */
    public function getClientDetails(int $clientId): array
    {
        return $this->makeRequest('GetClientsDetails', [
            'clientid' => $clientId,
        ]);
    }

    /**
     * Get client products/services
     */
    public function getClientProducts(int $clientId): array
    {
        return $this->makeRequest('GetClientsProducts', [
            'clientid' => $clientId,
        ]);
    }

    /**
     * Get client domains
     */
    public function getClientDomains(int $clientId): array
    {
        return $this->makeRequest('GetClientsDomains', [
            'clientid' => $clientId,
        ]);
    }

    /**
     * Get all products (services definitions) from WHMCS
     */
    public function getProducts(): array
    {
        return $this->makeRequest('GetProducts', [
            // No specific params needed for all products
        ]);
    }

    /**
     * Get client invoices
     */
    public function getClientInvoices(int $clientId): array
    {
        return $this->makeRequest('GetInvoices', [
            'userid' => $clientId,
        ]);
    }

    /**
     * Get client tickets
     */
    public function getClientTickets(int $clientId): array
    {
        return $this->makeRequest('GetTickets', [
            'clientid' => $clientId,
        ]);
    }

    /**
     * Sync all clients from WHMCS
     */
    public function syncAllClients(): array
    {
        $synced = 0;
        $errors = [];
        $limitStart = 0;
        $limitNum = 100;

        do {
            $response = $this->getClients($limitStart, $limitNum);

            if (($response['result'] ?? '') !== 'success') {
                return ['success' => false, 'message' => $response['message'] ?? 'Failed to fetch clients'];
            }

            $clients = $response['clients']['client'] ?? [];

            foreach ($clients as $client) {
                try {
                    // Check if customer exists by WHMCS ID
                    $customer = \App\Models\Customer::where('whmcs_id', $client['id'])->first();

                    // If not found, check by email to merge with existing manual customer
                    if (!$customer && !empty($client['email'])) {
                        $customer = \App\Models\Customer::where('email', $client['email'])->first();
                    }

                    if ($customer) {
                        // Update existing
                        $customer->update([
                            'whmcs_id' => $client['id'],
                            'name' => $client['firstname'] . ' ' . $client['lastname'],
                            'email' => $client['email'],
                            'phone' => $client['phonenumber'] ?? null,
                            'whatsapp' => $client['phonenumber'] ?? null,
                            'company' => $client['companyname'] ?? null,
                            'address' => implode(', ', array_filter([
                                $client['address1'] ?? '',
                                $client['address2'] ?? '',
                            ])),
                            'city' => $client['city'] ?? null,
                            'country' => $client['country'] ?? null,
                            'status' => strtolower($client['status'] ?? 'active'),
                            'source' => 'whmcs',
                        ]);
                    } else {
                        // Create new
                        \App\Models\Customer::create([
                            'whmcs_id' => $client['id'],
                            'name' => $client['firstname'] . ' ' . $client['lastname'],
                            'email' => $client['email'],
                            'phone' => $client['phonenumber'] ?? null,
                            'whatsapp' => $client['phonenumber'] ?? null,
                            'company' => $client['companyname'] ?? null,
                            'address' => implode(', ', array_filter([
                                $client['address1'] ?? '',
                                $client['address2'] ?? '',
                            ])),
                            'city' => $client['city'] ?? null,
                            'country' => $client['country'] ?? null,
                            'status' => strtolower($client['status'] ?? 'active'),
                            'source' => 'whmcs',
                        ]);
                    }
                    $synced++;
                } catch (\Exception $e) {
                    $errors[] = "Client {$client['id']} ({$client['email']}): {$e->getMessage()}";
                }
            }

            $limitStart += $limitNum;
            $totalClients = $response['totalresults'] ?? 0;

        } while ($limitStart < $totalClients);

        return [
            'success' => true,
            'synced' => $synced,
            'errors' => $errors,
        ];
    }

    /**
     * Sync all invoices from WHMCS
     */
    public function syncAllInvoices(): array
    {
        $synced = 0;
        $errors = [];
        $limitStart = 0;
        $limitNum = 100;

        do {
            $response = $this->makeRequest('GetInvoices', [
                'limitstart' => $limitStart,
                'limitnum' => $limitNum,
            ]);

            if (($response['result'] ?? '') !== 'success') {
                return ['success' => false, 'message' => $response['message'] ?? 'Failed to fetch invoices'];
            }

            $invoices = $response['invoices']['invoice'] ?? [];

            foreach ($invoices as $whmcsInvoice) {
                try {
                    \DB::transaction(function () use ($whmcsInvoice, &$synced) {
                        $customer = \App\Models\Customer::where('whmcs_id', $whmcsInvoice['userid'])->first();

                        if (!$customer) {
                            // Try to sync this client first if missing
                            $this->getClientDetails($whmcsInvoice['userid']);
                            // This won't automatically sync to DB unless we call sync logic, 
                            // we rely on daily client sync usually, but for now we skip if client missing or log error.
                            throw new \Exception("Customer with WHMCS ID {$whmcsInvoice['userid']} not found locally.");
                        }

                        $invoice = \App\Models\Invoice::updateOrCreate(
                            ['whmcs_id' => $whmcsInvoice['id']],
                            [
                                'customer_id' => $customer->id,
                                'code' => 'WHMCS-' . $whmcsInvoice['invoicenum'],
                                'status' => strtolower($whmcsInvoice['status']),
                                'date' => $whmcsInvoice['date'],
                                'due_date' => $whmcsInvoice['duedate'],
                                'subtotal' => $whmcsInvoice['subtotal'],
                                'tax_percent' => 0, // WHMCS tax is in tax/tax2
                                'tax_amount' => $whmcsInvoice['tax'] + $whmcsInvoice['tax2'],
                                'total' => $whmcsInvoice['total'],
                                'paid_amount' => $whmcsInvoice['status'] === 'Paid' ? $whmcsInvoice['total'] : 0,
                                'notes' => 'Imported from WHMCS',
                            ]
                        );

                        // If brand new invoice, create Accounting Journal Entry
                        if ($invoice->wasRecentlyCreated) {
                            $this->createAccountingEntryForInvoice($invoice);
                        }

                        $synced++;
                    });
                } catch (\Exception $e) {
                    $errors[] = "Invoice {$whmcsInvoice['id']}: {$e->getMessage()}";
                }
            }

            $limitStart += $limitNum;
            $totalInvoices = $response['totalresults'] ?? 0;

        } while ($limitStart < $totalInvoices);

        return [
            'success' => true,
            'synced' => $synced,
            'errors' => $errors,
        ];
    }

    /**
     * Create double-entry journal for imported invoice
     */
    protected function createAccountingEntryForInvoice($invoice)
    {
        $arAccount = \App\Models\Account::where('code', '1103')->first(); // Accounts Receivable
        $salesAccount = \App\Models\Account::where('code', '4100')->first(); // Sales Services

        if (!$arAccount || !$salesAccount)
            return;

        $entry = \App\Models\JournalEntry::create([
            'date' => $invoice->date,
            'description' => "WHMCS Invoice #{$invoice->code} - {$invoice->customer->name}",
            'reference' => $invoice->code,
            'is_manual' => false,
            'user_id' => 1,
        ]);

        // Debit: Accounts Receivable
        $entry->lines()->create([
            'account_id' => $arAccount->id,
            'debit' => $invoice->total,
            'credit' => 0,
            'description' => 'Accounts Receivable Increase',
        ]);

        // Credit: Sales Revenue
        $entry->lines()->create([
            'account_id' => $salesAccount->id,
            'debit' => 0,
            'credit' => $invoice->total,
            'description' => 'Revenue Recognition',
        ]);
    }

    /**
     * Sync all software licenses (products) from WHMCS
     */
    public function syncAllLicenses(): array
    {
        $synced = 0;
        $errors = [];
        $customers = \App\Models\Customer::whereNotNull('whmcs_id')->get();

        foreach ($customers as $customer) {
            try {
                $response = $this->getClientProducts($customer->whmcs_id);

                if (($response['result'] ?? '') !== 'success')
                    continue;

                $products = $response['products']['product'] ?? [];

                foreach ($products as $p) {
                    // Look for serial/license in custom fields or dedicated fields
                    $serial = null;

                    // Case 1: Checking for specific 'License Key' or similar in customfields
                    if (isset($p['customfields']['customfield'])) {
                        foreach ($p['customfields']['customfield'] as $cf) {
                            if (stripos($cf['name'], 'license') !== false || stripos($cf['name'], 'serial') !== false) {
                                $serial = $cf['value'];
                                break;
                            }
                        }
                    }

                    // Case 2: Some addons use dedicated 'licensekey' field
                    if (!$serial && !empty($p['licensekey'])) {
                        $serial = $p['licensekey'];
                    }

                    if ($serial) {
                        \App\Models\SoftwareLicense::updateOrCreate(
                            ['whmcs_id' => $p['id']],
                            [
                                'customer_id' => $customer->id,
                                'software_name' => $p['name'],
                                'serial_key' => $serial,
                                'start_date' => $p['regdate'] ?: null,
                                'end_date' => ($p['nextduedate'] && $p['nextduedate'] != '0000-00-00') ? $p['nextduedate'] : null,
                                'status' => strtolower($p['status']),
                            ]
                        );
                        $synced++;
                    }
                }
            } catch (\Exception $e) {
                $errors[] = "Customer {$customer->id}: {$e->getMessage()}";
            }
        }

        return [
            'success' => true,
            'synced' => $synced,
            'errors' => $errors,
        ];
    }
    /**
     * Get ticket details/replies
     */
    public function getTicketDetails(int $ticketId): array
    {
        return $this->makeRequest('GetTicket', [
            'ticketid' => $ticketId,
        ]);
    }

    /**
     * Add reply to a ticket
     */
    public function addTicketReply(int $ticketId, string $message, int $adminId = 1): array
    {
        return $this->makeRequest('AddTicketReply', [
            'ticketid' => $ticketId,
            'adminid' => $adminId,
            'message' => $message,
        ]);
    }

    /**
     * Get support departments from WHMCS
     */
    public function getSupportDepartments(): array
    {
        return $this->makeRequest('GetSupportDepartments');
    }

    /**
     * Open a new ticket in WHMCS
     */
    public function openTicket(int $clientId, int $deptId, string $subject, string $message, string $priority = 'Medium'): array
    {
        return $this->makeRequest('OpenTicket', [
            'clientid' => $clientId,
            'deptid' => $deptId,
            'subject' => $subject,
            'message' => $message,
            'priority' => $priority,
        ]);
    }
    /**
     * Sync all subscriptions (products) from WHMCS
     */
    public function syncAllSubscriptions(): array
    {
        $synced = 0;
        $errors = [];
        $customers = \App\Models\Customer::whereNotNull('whmcs_id')->get();

        foreach ($customers as $customer) {
            try {
                $response = $this->getClientProducts($customer->whmcs_id);

                if (($response['result'] ?? '') !== 'success') {
                    continue;
                }

                $products = $response['products']['product'] ?? [];

                foreach ($products as $p) {
                    // Map status
                    // WHMCS: Active, Suspended, Terminated, Cancelled, Fraud
                    // Local: active, suspended, cancelled
                    $status = strtolower($p['status']);
                    if (!in_array($status, ['active', 'suspended', 'cancelled'])) {
                        $status = 'cancelled'; // Default fallback
                        if ($p['status'] == 'Active')
                            $status = 'active';
                        if ($p['status'] == 'Suspended')
                            $status = 'suspended';
                    }

                    \App\Models\Subscription::updateOrCreate(
                        ['whmcs_service_id' => $p['id']],
                        [
                            'customer_id' => $customer->id,
                            'service_name' => $p['name'] . ($p['domain'] ? " - " . $p['domain'] : ""),
                            'price' => $p['recurringamount'] ?? 0,
                            'currency' => 'EGP', // Default, should ideally map currency
                            'billing_cycle' => $p['billingcycle'] ?? 'Monthly',
                            'start_date' => $p['regdate'] ?: null,
                            'next_due_date' => ($p['nextduedate'] && $p['nextduedate'] != '0000-00-00') ? $p['nextduedate'] : null,
                            'status' => $status,
                        ]
                    );
                    $synced++;
                }
            } catch (\Exception $e) {
                $errors[] = "Customer {$customer->id}: {$e->getMessage()}";
            }
        }

        return [
            'success' => true,
            'synced' => $synced,
            'errors' => $errors,
        ];
    }
}
