<?php

namespace Modules\CRMCore\App\Services;

use Modules\CRMCore\App\Models\Company;
use Modules\SystemCore\App\Models\CoreCustomer;

class BillingEntityDetector
{
    /**
     * Detect the billing entity based on available data
     * Priority: Customer > Company > Walk-in
     *
     * @param  array<string, mixed>  $data  Array containing possible entity IDs
     * @return array<string, mixed>|null
     */
    public function detect(array $data): ?array
    {
        // Check for customer_id first (highest priority) - now uses CoreCustomer
        if (! empty($data['customer_id'])) {
            $customer = CoreCustomer::with(['primaryContact', 'primaryAddress', 'company'])->find($data['customer_id']);
            if ($customer) {
                return [
                    'entity' => $customer,
                    'type' => 'customer',
                    'is_b2b' => $customer->isB2B(),
                    'billing_info' => $this->getCustomerBillingInfo($customer),
                ];
            }
        }

        // Check for company_id (B2B scenario)
        if (! empty($data['company_id'])) {
            $company = Company::with('customers')->find($data['company_id']);
            if ($company) {
                return [
                    'entity' => $company,
                    'type' => 'company',
                    'is_b2b' => true,
                    'billing_info' => $this->getCompanyBillingInfo($company),
                ];
            }
        }

        // Handle walk-in customer data
        if (! empty($data['customer_name']) || ! empty($data['customer_email'])) {
            return [
                'entity' => null,
                'type' => 'walk_in',
                'is_b2b' => false,
                'billing_info' => [
                    'name' => $data['customer_name'] ?? 'Walk-in Customer',
                    'email' => $data['customer_email'] ?? '',
                    'phone' => $data['customer_phone'] ?? '',
                    'address' => $this->formatWalkInAddress($data),
                    'tax_number' => $data['tax_number'] ?? '',
                    'tax_exempt' => $data['tax_exempt'] ?? false,
                ],
            ];
        }

        return null;
    }

    /**
     * Detect billing entity from a field order
     *
     * @param  object  $fieldOrder  Field order object
     * @return array<string, mixed>|null
     */
    public function detectFromFieldOrder(object $fieldOrder): ?array
    {
        return $this->detect([
            'customer_id' => $fieldOrder->customer_id ?? null,
            'company_id' => $fieldOrder->company_id ?? null,
            'customer_name' => $fieldOrder->customer_name ?? null,
            'customer_email' => $fieldOrder->customer_email ?? null,
            'customer_phone' => $fieldOrder->customer_phone ?? null,
            'billing_address' => $fieldOrder->billing_address ?? null,
            'billing_city' => $fieldOrder->billing_city ?? null,
            'billing_state' => $fieldOrder->billing_state ?? null,
            'billing_postal_code' => $fieldOrder->billing_postal_code ?? null,
            'billing_country' => $fieldOrder->billing_country ?? null,
            'tax_number' => $fieldOrder->tax_number ?? null,
            'tax_exempt' => $fieldOrder->tax_exempt ?? false,
        ]);
    }

    /**
     * Get billing information for a customer (CoreCustomer)
     *
     * @return array<string, mixed>
     */
    protected function getCustomerBillingInfo(CoreCustomer $customer): array
    {
        $primaryAddress = $customer->primaryAddress;
        $company = $customer->company;

        return [
            'name' => $customer->name,
            'email' => $customer->email,
            'phone' => $customer->phone ?? $customer->mobile,
            'address' => $primaryAddress?->full_address ?? '',
            'company_name' => $company?->name ?? $customer->company_name,
            'tax_number' => $customer->tax_id ?? $customer->vat_number,
            'tax_exempt' => $customer->tax_exempt,
            'payment_terms' => $customer->payment_terms,
            'credit_limit' => $customer->credit_limit,
            'discount_percentage' => $customer->discount_percentage,
        ];
    }

    /**
     * Get billing information for a company
     *
     * @return array<string, mixed>
     */
    protected function getCompanyBillingInfo(Company $company): array
    {
        return [
            'name' => $company->name,
            'email' => $company->email_office,
            'phone' => $company->phone_office,
            'address' => $this->formatCompanyAddress($company),
            'company_name' => $company->name,
            'tax_number' => null, // Companies might have tax info in different field
            'tax_exempt' => false,
            'payment_terms' => 'net30', // Default for B2B
            'credit_limit' => null,
            'discount_percentage' => 0,
        ];
    }

    /**
     * Format company address
     */
    protected function formatCompanyAddress(Company $company): string
    {
        $parts = array_filter([
            $company->address_street,
            $company->address_city,
            $company->address_state,
            $company->address_postal_code,
            $company->address_country,
        ]);

        return implode(', ', $parts);
    }

    /**
     * Format walk-in customer address
     *
     * @param  array<string, mixed>  $data
     */
    protected function formatWalkInAddress(array $data): string
    {
        $parts = array_filter([
            $data['billing_address'] ?? $data['delivery_address'] ?? '',
            $data['billing_city'] ?? $data['delivery_city'] ?? '',
            $data['billing_state'] ?? $data['delivery_state'] ?? '',
            $data['billing_postal_code'] ?? $data['delivery_postal_code'] ?? '',
            $data['billing_country'] ?? $data['delivery_country'] ?? '',
        ]);

        return implode(', ', $parts);
    }

    /**
     * Create or get customer from billing entity
     *
     * @param  array<string, mixed>  $billingEntity
     */
    public function ensureCustomerExists(array $billingEntity): ?CoreCustomer
    {
        // If already a customer, return it
        if ($billingEntity['type'] === 'customer') {
            return $billingEntity['entity'];
        }

        // For walk-in, create new CoreCustomer
        if ($billingEntity['type'] === 'walk_in') {
            $billingInfo = $billingEntity['billing_info'];

            return CoreCustomer::createFromFirstPurchase([
                'name' => $billingInfo['name'],
                'email' => $billingInfo['email'],
                'phone' => $billingInfo['phone'],
            ]);
        }

        // For company, find existing customer or create one
        if ($billingEntity['type'] === 'company' && $billingEntity['entity']) {
            /** @var Company $company */
            $company = $billingEntity['entity'];

            // Find existing customer for this company
            $existingCustomer = CoreCustomer::where('company_id', $company->id)->first();
            if ($existingCustomer) {
                return $existingCustomer;
            }

            // Create new customer linked to company
            return CoreCustomer::createFromFirstPurchase([
                'name' => $company->name,
                'company_name' => $company->name,
                'email' => $company->email_office,
                'phone' => $company->phone_office,
                'company_id' => $company->id,
                'customer_type' => 'b2b',
            ]);
        }

        return null;
    }
}
