<?php

namespace App\Services;

use App\DTOs\Admin\ContractSectionDto;
use App\Models\ContractSections;
use App\Models\SectionRule;
use Exception;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Log;

class ContractSectionService
{
    public function getContractSectionByTemplate(int $idTemplateSection, int $perPage = 10): LengthAwarePaginator
    {
        return ContractSections::where("template_section_id", "=", $idTemplateSection)
        ->orderBy("order", "asc")
        ->paginate($perPage);
    }

    public function create(ContractSectionDto $dto): ?ContractSections
    {
        try {
            $newData = ContractSections::create([
                "title" => $dto->title,
                "content" => $dto->content,
                "template_section_id" => $dto->template_section_id,
                'order' => $dto->order,
                'omit_rules' => $dto->omit_rules ? 1 : 0
            ]);
            $sectionRules = SectionRule::whereHas('templateSections', function ($q) use ($dto) {
                $q->where('template_section_id', $dto->template_section_id);
            })->get()->keyBy('id');

            foreach ($dto->rules as $ruleId => $value) {
                if ($value === null) {
                    continue;
                }

                if (isset($sectionRules[$ruleId])) {
                    $rule = $sectionRules[$ruleId];
                    $newData->rules()->create([
                        'field_name' => $rule->key,
                        'operator' => '=',
                        'value' => $value,
                    ]);
                }
            }
            return $newData;
        } catch (Exception $e) {
            Log::error('Error al crear la sección del contrato: ' . $e->getMessage(), [
                'data' => $dto,
                'trace' => $e->getTraceAsString(),
            ]);
            return null;
        }
    }

    public function find($id): ?ContractSectionDto
    {
        try {
            $data = ContractSections::with('rules')->findOrFail($id);
            $rules = [];
            foreach ($data->rules as $rule) {
                $rules[$rule->field_name] = $rule->value;
            }

            return new ContractSectionDto([
                "id" => $data->id,
                'title' => $data->title,
                'content' => $data->content,
                "rules" => $rules,
                'order' => $data->order,
                'omit_rules' => $data->omit_rules
            ]);
        } catch (Exception $e) {
            Log::error('No se pudo encontrar la sección del contrato: ' . $e->getMessage(), [
                'data' => $id,
                'trace' => $e->getTraceAsString(),
            ]);
            return null;
        }
    }

    public function update(int $id, ContractSectionDto $dto): bool
    {
        try {
            $section = ContractSections::findOrFail($id);
            // Actualizar datos básicos
            $section->update([
                "title" => $dto->title,
                "content" => $dto->content,
                'order' => $dto->order,
                'omit_rules' => $dto->omit_rules ? 1 : 0
            ]);

            $sectionRules = SectionRule::whereHas('templateSections', function ($q) use ($section) {
                $q->where('template_section_id', $section->template_section_id);
            })->get()->keyBy('id');

            $currentRules = $section->rules()->get()->keyBy('field_name');

            $processedFields = [];

            foreach ($dto->rules as $ruleId => $value) {
                if ($value === null) {
                    continue;
                }

                if (!isset($sectionRules[$ruleId])) {
                    continue;
                }

                $rule = $sectionRules[$ruleId];
                $fieldName = $rule->key; // Usamos la columna 'key' directamente
                $processedFields[] = $fieldName;

                if ($currentRules->has($fieldName)) {
                    // Ya existe → actualizar
                    $currentRules[$fieldName]->update([
                        'value' => $value,
                    ]);
                } else {
                    // No existe → crear
                    $section->rules()->create([
                        'field_name' => $fieldName,
                        'operator' => '=',
                        'value' => $value,
                    ]);
                }
            }

            $section->rules()
                ->whereNotIn('field_name', $processedFields)
                ->delete();

            return true;
        } catch (Exception $e) {
            Log::error('Error al actualizar la sección del contrato: ' . $e->getMessage(), [
                'id' => $id,
                'data' => $dto,
                'trace' => $e->getTraceAsString(),
            ]);
            return false;
        }
    }


    public function delete(int $id): bool
    {
        try {
            $deleteItem = ContractSections::findOrFail($id);
            $deleteItem->delete();
            return true;
        } catch (Exception $e) {
            Log::error('Error al eliminar la sección del contrato: ' . $e->getMessage(), [
                'id' => $id,
                'trace' => $e->getTraceAsString(),
            ]);
            return false;
        }
    }
}