<?php

namespace App\Domain\Identity\Services;

use App\Domain\Identity\DTOs\NationalIdData;
use Carbon\Carbon;

class NationalIdService
{
    public function parse(string $nationalId): ?NationalIdData
    {
        if (!$this->isValid($nationalId)) {
            return null;
        }

        $century = (int) $nationalId[0];
        $year = (int) substr($nationalId, 1, 2);
        $month = (int) substr($nationalId, 3, 2);
        $day = (int) substr($nationalId, 5, 2);
        $governorateCode = substr($nationalId, 7, 2);
        $genderDigit = (int) $nationalId[12];

        $fullYear = ($century === 2 ? 1900 : 2000) + $year;
        $birthDate = Carbon::createFromDate($fullYear, $month, $day);
        $gender = $genderDigit % 2 === 0 ? 'female' : 'male';
        $governorate = self::GOVERNORATES[$governorateCode] ?? 'Unknown';

        return new NationalIdData(
            birthDate: $birthDate,
            gender: $gender,
            governorate: $governorate,
            governorateCode: $governorateCode,
        );
    }

    public function isValid(string $nationalId): bool
    {
        // Must be exactly 14 digits
        if (!preg_match('/^\d{14}$/', $nationalId)) {
            return false;
        }
        // Century must be 2 or 3
        $century = (int) $nationalId[0];
        if ($century !== 2 && $century !== 3) {
            return false;
        }
        // Month 01-12
        $month = (int) substr($nationalId, 3, 2);
        if ($month < 1 || $month > 12) {
            return false;
        }
        // Day 01-31
        $day = (int) substr($nationalId, 5, 2);
        if ($day < 1 || $day > 31) {
            return false;
        }
        return true;
    }

    private const GOVERNORATES = [
        '01' => 'Cairo', '02' => 'Alexandria', '03' => 'Port Said',
        '04' => 'Suez', '11' => 'Damietta', '12' => 'Dakahlia',
        '13' => 'Sharqia', '14' => 'Qalyubia', '15' => 'Kafr El Sheikh',
        '16' => 'Gharbia', '17' => 'Monufia', '18' => 'Beheira',
        '19' => 'Ismailia', '21' => 'Giza', '22' => 'Beni Suef',
        '23' => 'Fayoum', '24' => 'Minya', '25' => 'Asyut',
        '26' => 'Sohag', '27' => 'Qena', '28' => 'Aswan',
        '29' => 'Luxor', '31' => 'Red Sea', '32' => 'New Valley',
        '33' => 'Matrouh', '34' => 'North Sinai', '35' => 'South Sinai',
        '88' => 'Foreign',
    ];
}
