<?php

declare(strict_types=1);

final class HyroLeadService
{
    public function __construct(
        private readonly HyroLeadRepository $repository,
        private readonly array $countries
    ) {
    }

    public function validate(array $input): array
    {
        $errors = [];

        $companyName = trim(
            (string) ($input['company_name'] ?? '')
        );

        $contactName = trim(
            (string) ($input['contact_name'] ?? '')
        );

        $email = trim(
            (string) ($input['email'] ?? '')
        );

        $phone = trim(
            (string) ($input['phone'] ?? '')
        );

        $countryCode = strtoupper(
            trim((string) ($input['country_code'] ?? ''))
        );

        $productCode = strtoupper(
            trim((string) ($input['product_code'] ?? 'SPA'))
        );

        if (
            $companyName === '' ||
            mb_strlen($companyName) < 2
        ) {
            $errors['company_name'] =
                'Please enter a valid company name.';
        }

        if (
            $contactName === '' ||
            mb_strlen($contactName) < 2
        ) {
            $errors['contact_name'] =
                'Please enter the contact person name.';
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errors['email'] =
                'Please enter a valid email address.';
        }

        if (
            $phone === '' ||
            mb_strlen($phone) < 7 ||
            mb_strlen($phone) > 40
        ) {
            $errors['phone'] =
                'Please enter a valid phone number.';
        }

        if (!isset($this->countries[$countryCode])) {
            $errors['country_code'] =
                'Please select a valid country.';
        }

        $allowedProducts = [
            'SPA',
            'GYM',
            'ACCOUNTING',
            'RETAIL',
            'CRM',
            'SCHOOL',
        ];

        if (!in_array(
            $productCode,
            $allowedProducts,
            true
        )) {
            $errors['product_code'] =
                'Please select a valid product.';
        }

        $preferredDate = trim(
            (string) ($input['preferred_date'] ?? '')
        );

        if ($preferredDate !== '') {
            $date = DateTimeImmutable::createFromFormat(
                'Y-m-d',
                $preferredDate
            );

            if (
                !$date ||
                $date->format('Y-m-d') !== $preferredDate
            ) {
                $errors['preferred_date'] =
                    'Please select a valid date.';
            }
        }

        return $errors;
    }

    public function create(array $input): array
    {
        $countryCode = strtoupper(
            trim((string) $input['country_code'])
        );

        $country = $this->countries[$countryCode];

        $now = date('Y-m-d H:i:s');

        $leadCode = $this->generateLeadCode();

        $lead = [
            'lead_code' => $leadCode,

            'request_type' => 'book_demo',

            'product_code' => strtoupper(
                trim((string) ($input['product_code'] ?? 'SPA'))
            ),

            'company_name' => trim(
                (string) $input['company_name']
            ),

            'contact_name' => trim(
                (string) $input['contact_name']
            ),

            'email' => strtolower(
                trim((string) $input['email'])
            ),

            'phone' => trim(
                (string) $input['phone']
            ),

            'country_code' => $countryCode,
            'country_name' => $country['name'],

            'city' => $this->nullableString(
                $input['city'] ?? null
            ),

            'preferred_date' => $this->nullableString(
                $input['preferred_date'] ?? null
            ),

            'preferred_time' => $this->nullableString(
                $input['preferred_time'] ?? null
            ),

            'timezone' => $country['timezone'],

            'message' => $this->nullableString(
                $input['message'] ?? null
            ),

            'source_page' => $this->nullableString(
                $input['source_page'] ?? null
            ),

            'source_campaign' => $this->nullableString(
                $input['source_campaign'] ?? null
            ),

            'status' => 'new',
            'assigned_to' => null,

            'ip_address' => $this->clientIp(),

            'user_agent' => mb_substr(
                (string) ($_SERVER['HTTP_USER_AGENT'] ?? ''),
                0,
                500
            ),

            'created_at' => $now,
            'updated_at' => $now,
        ];

        $leadId = $this->repository->create($lead);

        hyro_log(
            'leads',
            'New Book Demo lead created.',
            [
                'lead_id' => $leadId,
                'lead_code' => $leadCode,
                'product_code' => $lead['product_code'],
            ]
        );

        return [
            'id' => $leadId,
            'lead_code' => $leadCode,
        ];
    }

    private function generateLeadCode(): string
    {
        return sprintf(
            'LEAD-%s-%s',
            date('YmdHis'),
            strtoupper(bin2hex(random_bytes(3)))
        );
    }

    private function nullableString(
        mixed $value
    ): ?string {
        $value = trim((string) $value);

        return $value === ''
            ? null
            : $value;
    }

    private function clientIp(): ?string
    {
        $ip = $_SERVER['REMOTE_ADDR'] ?? null;

        if (
            !is_string($ip) ||
            !filter_var($ip, FILTER_VALIDATE_IP)
        ) {
            return null;
        }

        return $ip;
    }
}
