<?php

namespace App\Models\ProjetosProgramas;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use DateTimeInterface;

class ProjetoPrograma extends Model {
    use HasFactory;

    protected $connection = 'mysql';
    public $incrementing = false;
    protected $keyType = 'string';
    protected $table = 'projects_programs';

    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at';

    protected $fillable = [
        'id',
        'created_at',
        'updated_at',
        'denominacao',
        'num_processo_adm',
        'empresa_licitada',
        'gestor_structure_id',
        'tipo_id',
        'programa_ppa',
        'project_program_id',
        'endereco',
        'cep',
        'latitude',
        'longitude',
        'bairro',
        'data_inicio',
        'data_termino',
        'prazo_id',
        'prazo_entrega_dias',
        'prazo_entrega_competencia',
        'codigo',
        'acompanhamento_governo',
        'acompanhamento_prioritario',
        'classificacao_id',
        'etapa_id',
        'project_objective_id',
        'numero_ordem',
        'relacao_ppa',
        'prioritario',
        'ordem_prioridade',
        'prioridade_origem',
        'prioridade_definida_por_user_id',
        'andamento',
        'andamento_cor',
        'orcamento_previsto',
        'orcamento_disponivel',
        'orcamento_status_cor',
        'show_metas_relatorio',
        'eixo_id',
        'area_id',
        'contato_nome',
        'contato_matricula',
        'contato_ramal',
        'contato_telefone',
        'contato_email',
        'descricao_objeto',
        'justificativa',
        'descricao_responsabilidades',
        'status_id',
        'dificuldade_id',
        'gargalos',
        'observacoes',
        'fonte_id',
        'fonte_outro',
        'custo_total',
        'custeio_anual',
        'ppa_2022', 'ppa_2023', 'ppa_2024', 'ppa_2025',
        'loa_2022', 'loa_2023', 'loa_2024', 'loa_2025',
        'manutencao_2022', 'manutencao_2023', 'manutencao_2024', 'manutencao_2025',
        'conve_orgao', 'conve_orgao_outro', 'conve_proposta', 'conve_convenio',
        'status_registro',
        'identificacao_done', 'cronograma_done', 'areas_done', 'contato_done', 'dados_done', 'investimento_done',
    ];

    protected $casts = [
        'acompanhamento_governo' => 'boolean',
        'acompanhamento_prioritario' => 'boolean',
        'data_inicio' => 'date',
        'data_termino' => 'date',
        'prazo_entrega_dias' => 'integer',
        'custo_total' => 'decimal:2',
        'custeio_anual' => 'decimal:2',
        'orcamento_previsto' => 'decimal:2',
        'orcamento_disponivel' => 'decimal:2',
        'ppa_2022' => 'decimal:2',
        'ppa_2023' => 'decimal:2',
        'ppa_2024' => 'decimal:2',
        'ppa_2025' => 'decimal:2',
        'loa_2022' => 'decimal:2',
        'loa_2023' => 'decimal:2',
        'loa_2024' => 'decimal:2',
        'loa_2025' => 'decimal:2',
        'manutencao_2022' => 'decimal:2',
        'manutencao_2023' => 'decimal:2',
        'manutencao_2024' => 'decimal:2',
        'manutencao_2025' => 'decimal:2',
        'identificacao_done' => 'boolean',
        'cronograma_done' => 'boolean',
        'areas_done' => 'boolean',
        'contato_done' => 'boolean',
        'dados_done' => 'boolean',
        'investimento_done' => 'boolean',
        'prioritario' => 'boolean',
        'ordem_prioridade' => 'integer',
        'show_metas_relatorio' => 'boolean',
        'latitude' => 'float',
        'longitude' => 'float',
    ];

    public static function boot() {
        parent::boot();
        static::creating(function ($model) {
            $model->id = Str::uuid();
            $model->status_registro = $model->status_registro ?: 'EM_EDICAO';
        });
    }

    public function gestor() {
        return $this->belongsTo(\App\Models\Structure::class, 'gestor_structure_id', 'id');
    }

    public function prioridadeDefinidaPor(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(\App\Models\User::class, 'prioridade_definida_por_user_id', 'id');
    }

    public function tipo() {
        return $this->belongsTo(Tipo::class, 'tipo_id');
    }

    public function prazo() {
        return $this->belongsTo(Prazo::class, 'prazo_id');
    }

    public function classificacao() {
        return $this->belongsTo(Classificacao::class, 'classificacao_id');
    }

    public function etapa() {
        return $this->belongsTo(Etapa::class, 'etapa_id');
    }

    public function fonte() {
        return $this->belongsTo(Fonte::class, 'fonte_id');
    }

    public function eixo() {
        return $this->belongsTo(Eixo::class, 'eixo_id');
    }

    public function area() {
        return $this->belongsTo(Area::class, 'area_id');
    }

    public function ods() {
        return $this->belongsToMany(Ods::class, 'project_program_ods', 'project_id', 'ods_id');
    }

    public function orgaosEnvolvidos() {
        return $this->belongsToMany(\App\Models\Structure::class, 'project_program_orgaos', 'project_id', 'structure_id');
    }

    public function anexos() {
        return $this->hasMany(Anexo::class, 'project_id')->whereNull('history_id');
    }

    public function todosAnexos() {
        return $this->hasMany(Anexo::class, 'project_id');
    }

    public function programa(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(Programa::class, 'project_program_id');
    }

    public function objetivo(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(Objetivo::class, 'project_objective_id');
    }

    public function historicos(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(ProjetoProgramaHistorico::class, 'project_id');
    }

    public function getPpaTotalAttribute() {
        return ($this->ppa_2022 ?? 0) + ($this->ppa_2023 ?? 0) + ($this->ppa_2024 ?? 0) + ($this->ppa_2025 ?? 0);
    }

    public function getLoaTotalAttribute() {
        return ($this->loa_2022 ?? 0) + ($this->loa_2023 ?? 0) + ($this->loa_2024 ?? 0) + ($this->loa_2025 ?? 0);
    }

    public function getManutencaoTotalAttribute() {
        return ($this->manutencao_2022 ?? 0) + ($this->manutencao_2023 ?? 0) + ($this->manutencao_2024 ?? 0) + ($this->manutencao_2025 ?? 0);
    }

    public function getStatusRegistroLabelAttribute(): string {
        return $this->status_registro === 'COMPLETO' ? 'Concluído' : 'Em edição';
    }

    public function getStatusRegistroBadgeClassAttribute(): string {
        return $this->status_registro === 'COMPLETO' ? 'success' : 'warning';
    }

    /**
     * Cadastro finalizado (todas as etapas concluídas), elegível a priorização no MAPÃO.
     */
    public function isCadastroCompleto(): bool {
        return $this->status_registro === 'COMPLETO';
    }

    public function getProgramaPpaCodigoAttribute(): ?string {
        $list = config('projetos_programas.programas_ppa', []);
        $key = array_search($this->programa_ppa, $list, true);
        return $key === false ? null : $key;
    }

    public function getBairroCodigoAttribute(): ?string {
        $list = config('projetos_programas.bairros', []);
        $key = array_search($this->bairro, $list, true);
        return $key === false ? null : $key;
    }

    /**
     * Rótulo persistido no banco para projetos com abrangência em todos os bairros.
     */
    public static function bairroTodosRotulo(): string
    {
        $codigo = (string) config('projetos_programas.bairro_codigo_todos', 'todos');

        return (string) (config('projetos_programas.bairros')[$codigo] ?? 'Todos');
    }

    public function isBairroTodos(): bool
    {
        $bairro = $this->bairro;

        return $bairro !== null && $bairro !== '' && $bairro === self::bairroTodosRotulo();
    }

    public function bairroRotuloExibicao(): string
    {
        if ($this->isBairroTodos()) {
            return (string) __('Todos os bairros');
        }

        return (string) ($this->bairro ?? '');
    }

    /**
     * Rótulo curto para colunas estreitas da listagem (ex.: tabela MAPÃO).
     */
    public function bairroRotuloListagem(): string
    {
        if ($this->isBairroTodos()) {
            return (string) __('Todos');
        }

        return (string) ($this->bairro ?? '');
    }

    /**
     * Coordenadas para exibição na aba Mapa.
     * Projetos com bairro "Todos" usam referência municipal (centro + leve deslocamento).
     *
     * @return array{latitude: float, longitude: float, referencia_municipio: bool}|null
     */
    public function coordenadasMapa(int $indiceReferenciaMunicipio = 0): ?array
    {
        if ($this->isBairroTodos()) {
            return $this->coordenadasReferenciaMunicipio($indiceReferenciaMunicipio);
        }

        if (!is_numeric($this->latitude) || !is_numeric($this->longitude)) {
            return null;
        }

        $lat = (float) $this->latitude;
        $lng = (float) $this->longitude;

        if ($lat < -90.0 || $lat > 90.0 || $lng < -180.0 || $lng > 180.0) {
            return null;
        }

        return [
            'latitude' => $lat,
            'longitude' => $lng,
            'referencia_municipio' => false,
        ];
    }

    /**
     * @return array{latitude: float, longitude: float, referencia_municipio: true}
     */
    private function coordenadasReferenciaMunicipio(int $indice): array
    {
        $centerLat = (float) config('projetos_programas.mapa_centro_latitude', -23.0067);
        $centerLng = (float) config('projetos_programas.mapa_centro_longitude', -44.3180);
        $idx = max(0, $indice);

        $angle = $idx * 2.399963229728653;
        $ring = intdiv($idx, 8);
        $radius = 0.0018 * (1 + $ring);

        return [
            'latitude' => $centerLat + ($radius * cos($angle)),
            'longitude' => $centerLng + ($radius * sin($angle)),
            'referencia_municipio' => true,
        ];
    }

    /**
     * Formata `prazo_entrega_competencia` (AAAA-MM) como MM/AAAA para exibição (MAPÃO, relatórios).
     */
    public function prazoEntregaCompetenciaMesAnoFormatado(): ?string {
        $c = $this->prazo_entrega_competencia;
        if ($c === null || $c === '' || !preg_match('/^(\d{4})-(0[1-9]|1[0-2])$/', (string) $c, $m)) {
            return null;
        }

        return $m[2] . '/' . $m[1];
    }

    /**
     * Texto multilinha para relatórios: mês/ano (quando houver) e quantidade de dias.
     */
    public function textoPrazoImplantacaoRelatorio(): string {
        $lines = [];
        $mesAno = $this->prazoEntregaCompetenciaMesAnoFormatado();
        if ($mesAno !== null) {
            $lines[] = $mesAno;
        }
        if ($this->prazo_entrega_dias !== null && $this->prazo_entrega_dias !== '') {
            $lines[] = ((string) $this->prazo_entrega_dias) . ' ' . __('dias');
        }

        return implode("\n", $lines);
    }

    protected function serializeDate(DateTimeInterface $date) {
        return $date->format('Y-m-d H:i:s');
    }
}
