<?php

namespace Controllers;

use Firebase\JWT\JWT;
use Libs\ResponseLib;
use Models\UserModel;
use Services\TshieldService;
use Psr\Http\Message\ServerRequestInterface;
use Respect\Validation\Validator as val;
use Respect\Validation\Exceptions\ValidationException;

class LoginController
{
    private UserModel $userModel;
    private TshieldService $tshieldService;

    public function __construct()
    {
        $this->userModel = new UserModel();
        $this->tshieldService = new TshieldService();
    }

    public function __invoke(ServerRequestInterface $request)
    {
        $body = json_decode((string) $request->getBody(), true) ?? [];

        try {
            val::key('email', val::email())
                ->key('password', val::stringType()->notEmpty()->length(8, null))
                ->assert($body);
        } catch (ValidationException $e) {
            return ResponseLib::sendFail("Validation failed: " . $e->getFullMessage(), [], "E_VALIDATE")->withStatus(401);
        }

        $email = $body['email'];
        $password = $body['password'];

        $user = $this->userModel->validateLogin($email, $password);

        if (!$user) {
            return ResponseLib::sendFail("Invalid credentials", [], "E_VALIDATE")->withStatus(401);
        }

        $kycStatus = (int)($user['user_kyc'] ?? 0);
        $roleId = (int)($user['role_id'] ?? 0);

        if ($kycStatus === 0) {
            if ($roleId === 1) {
                return ResponseLib::sendFail(
                    'Necessário finalizar análise PJ ou contatar o suporte.',
                    ['reason' => 'KYC_PJ_PENDING'],
                    'E_KYC'
                )->withStatus(403);
            }

            $analysisPayload = [
                'name' => $user['user_name'] ?? $user['user_email'],
                'document' => $this->buildDocumentPayload($user['user_cpf'] ?? ''),
                'email' => $user['user_email'],
                'phone' => $user['user_phone'] ?? '',
                'birthdate' => $this->formatBirthdate($user['user_birthdate'] ?? null),
            ];

            if (empty($analysisPayload['document']['documentNumber'])) {
                return ResponseLib::sendFail(
                    'CPF não cadastrado. Contate o suporte para concluir a verificação.',
                    ['reason' => 'KYC_PF_MISSING_DOCUMENT'],
                    'E_KYC'
                )->withStatus(403);
            }

            try {
                $tshield = $this->tshieldService->generateIndividualLink(
                    (int)$user['user_id'],
                    $analysisPayload
                );
            } catch (\Throwable $e) {
                return ResponseLib::sendFail(
                    'Não foi possível gerar o link de verificação: ' . $e->getMessage(),
                    [],
                    'E_EXTERNAL'
                )->withStatus(502);
            }

            return ResponseLib::sendFail(
                'KYC pendente. Conclua a verificação pelo link disponibilizado.',
                [
                    'link' => $tshield['link'],
                    'numberToken' => $tshield['number'],
                ],
                'E_KYC'
            )->withStatus(403);
        }

        $payload = [
            'sub' => $user['user_id'],
            'email' => $user['user_email'],
            'iat' => time(),
            'exp' => time() + 3600
        ];
        $jwt = JWT::encode($payload, $_ENV['JWT_SECRET'], 'HS256');

        return ResponseLib::sendOk(['token' => $jwt, 'user_id' => $user['user_id'], 'company_id' => $user['company_id']]);
    }

    private function buildDocumentPayload(?string $cpf): array
    {
        $number = preg_replace('/\D+/', '', (string)$cpf);
        return [
            'documentNumber' => $number,
            'documentType' => 'CPF',
        ];
    }

    private function formatBirthdate($value): ?string
    {
        if ($value === null || $value === '') {
            return null;
        }

        if (is_numeric($value)) {
            $numeric = (string)$value;
            $timestamp = (int)$value;

            if ($timestamp > 0) {
                if (strlen($numeric) === 8) {
                    $formatted = \DateTimeImmutable::createFromFormat('Ymd', $numeric);
                    if ($formatted) {
                        return $formatted->format('Y-m-d');
                    }
                }

                if (strlen($numeric) >= 13) {
                    $timestamp = (int) floor($timestamp / 1000);
                }

                if ($timestamp >= 1000000000) {
                    $dt = (new \DateTimeImmutable())->setTimestamp($timestamp);
                    return $dt->format('Y-m-d');
                }
            }
        }

        if (is_string($value)) {
            $value = trim($value);

            if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
                return $value;
            }

            if (preg_match('/^\d{8}$/', $value)) {
                $formatted = \DateTimeImmutable::createFromFormat('Ymd', $value);
                if ($formatted) {
                    return $formatted->format('Y-m-d');
                }
            }

            foreach (['d/m/Y', 'd-m-Y', 'Y/m/d', 'Y.m.d'] as $fmt) {
                $formatted = \DateTimeImmutable::createFromFormat($fmt, $value);
                if ($formatted) {
                    return $formatted->format('Y-m-d');
                }
            }
        }

        return null;
    }

    private function formatAddress(array $user): ?string
    {
        $parts = array_filter([
            $user['user_address'] ?? null,
            $user['user_city'] ?? null,
            $user['user_state'] ?? null,
            $user['user_zip'] ?? null,
            $user['user_country'] ?? null,
        ]);

        return empty($parts) ? null : implode(', ', $parts);
    }
}