<?php

namespace App\Controllers;

use App\Models\SiteModel;
use App\Models\TurbineModel;

class Turbines extends BaseController
{
    private TurbineModel $model;
    private SiteModel $sites;

    public function __construct()
    {
        $this->model = new TurbineModel();
        $this->sites = new SiteModel();
    }

    public function index()
    {
        if ($redirect = $this->requireOrganizationContext()) {
            return $redirect;
        }

        $query = $this->model->withRelations();

        if (! $this->isPlatformAdmin()) {
            $query->where('sites.organization_id', (int) $this->currentOrganizationId());
        }

        return view('turbines/index', [
            'title' => 'Turbinas',
            'active' => 'turbines',
            'turbines' => $query->orderBy('turbines.turbine_code', 'ASC')->findAll(),
        ]);
    }

    public function new()
    {
        if ($redirect = $this->requireOrganizationContext()) {
            return $redirect;
        }

        if (! $this->canManageOperations()) {
            return redirect()->to(site_url('turbines'))->with('error', 'Nao tens permissao para criar turbinas.');
        }

        return view('turbines/form', [
            'title' => 'Nova turbina',
            'active' => 'turbines',
            'turbine' => null,
            'sites' => $this->siteOptions(),
            'action' => site_url('turbines'),
        ]);
    }

    public function create()
    {
        if (! $this->canManageOperations()) {
            return redirect()->to(site_url('turbines'))->with('error', 'Nao tens permissao para criar turbinas.');
        }

        $data = $this->collectData();
        if (! $this->validateData($data, $this->rules())) {
            return redirect()->back()->withInput()->with('error', 'Verifica os campos obrigatorios da turbina.');
        }

        if (! $this->siteBelongsToCurrentOrganization((int) $data['site_id'])) {
            return redirect()->back()->withInput()->with('error', 'O site selecionado nao pertence a organizacao ativa.');
        }

        if ($this->turbineCodeExists((int) $data['site_id'], $data['turbine_code'])) {
            return redirect()->back()->withInput()->with('error', 'Ja existe uma turbina com esse codigo nesse site.');
        }

        $this->model->insert($data);

        return redirect()->to(site_url('turbines'))->with('success', 'Turbina criada com sucesso.');
    }

    public function edit(int $id)
    {
        $turbine = $this->model->find($id);
        if (! $turbine || ! $this->canAccessTurbine($turbine)) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound('Turbina nao encontrada.');
        }

        if (! $this->canManageOperations()) {
            return redirect()->to(site_url('turbines'))->with('error', 'Nao tens permissao para editar turbinas.');
        }

        return view('turbines/form', [
            'title' => 'Editar turbina',
            'active' => 'turbines',
            'turbine' => $turbine,
            'sites' => $this->siteOptions(),
            'action' => site_url('turbines/' . $id),
        ]);
    }

    public function update(int $id)
    {
        $turbine = $this->model->find($id);
        if (! $turbine || ! $this->canAccessTurbine($turbine)) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound('Turbina nao encontrada.');
        }

        if (! $this->canManageOperations()) {
            return redirect()->to(site_url('turbines'))->with('error', 'Nao tens permissao para editar turbinas.');
        }

        $data = $this->collectData();
        if (! $this->validateData($data, $this->rules())) {
            return redirect()->back()->withInput()->with('error', 'Verifica os campos obrigatorios da turbina.');
        }

        if (! $this->siteBelongsToCurrentOrganization((int) $data['site_id'])) {
            return redirect()->back()->withInput()->with('error', 'O site selecionado nao pertence a organizacao ativa.');
        }

        if ($this->turbineCodeExists((int) $data['site_id'], $data['turbine_code'], $id)) {
            return redirect()->back()->withInput()->with('error', 'Ja existe uma turbina com esse codigo nesse site.');
        }

        $this->model->update($id, $data);

        return redirect()->to(site_url('turbines'))->with('success', 'Turbina atualizada com sucesso.');
    }

    public function delete(int $id)
    {
        $turbine = $this->model->find($id);
        if (! $turbine || ! $this->canAccessTurbine($turbine)) {
            return redirect()->to(site_url('turbines'))->with('error', 'Turbina nao encontrada.');
        }

        if (! $this->canManageOperations()) {
            return redirect()->to(site_url('turbines'))->with('error', 'Nao tens permissao para remover turbinas.');
        }

        $this->model->delete($id);

        return redirect()->to(site_url('turbines'))->with('success', 'Turbina removida com sucesso.');
    }

    private function collectData(): array
    {
        return [
            'site_id' => (int) $this->request->getPost('site_id'),
            'turbine_code' => trim((string) $this->request->getPost('turbine_code')),
            'name' => trim((string) $this->request->getPost('name')) ?: null,
            'manufacturer' => trim((string) $this->request->getPost('manufacturer')) ?: null,
            'model' => trim((string) $this->request->getPost('model')) ?: null,
            'serial_number' => trim((string) $this->request->getPost('serial_number')) ?: null,
            'rated_power_kw' => $this->nullableDecimal($this->request->getPost('rated_power_kw')),
            'hub_height_m' => $this->nullableDecimal($this->request->getPost('hub_height_m')),
            'rotor_diameter_m' => $this->nullableDecimal($this->request->getPost('rotor_diameter_m')),
            'commissioned_at' => trim((string) $this->request->getPost('commissioned_at')) ?: null,
            'status' => trim((string) $this->request->getPost('status')) ?: 'active',
        ];
    }

    private function rules(): array
    {
        return [
            'site_id' => 'required|integer',
            'turbine_code' => 'required|max_length[80]',
            'name' => 'permit_empty|max_length[160]',
            'manufacturer' => 'permit_empty|max_length[120]',
            'model' => 'permit_empty|max_length[120]',
            'serial_number' => 'permit_empty|max_length[120]',
            'rated_power_kw' => 'permit_empty|decimal',
            'hub_height_m' => 'permit_empty|decimal',
            'rotor_diameter_m' => 'permit_empty|decimal',
            'commissioned_at' => 'permit_empty|valid_date[Y-m-d]',
            'status' => 'required|in_list[active,inactive,pending,maintenance]',
        ];
    }

    private function siteOptions(): array
    {
        $query = $this->sites->withOrganization();

        if (! $this->isPlatformAdmin()) {
            $query->where('sites.organization_id', (int) $this->currentOrganizationId());
        }

        return $query->orderBy('sites.name', 'ASC')->findAll();
    }

    private function siteBelongsToCurrentOrganization(int $siteId): bool
    {
        if ($this->isPlatformAdmin()) {
            return true;
        }

        $site = $this->sites->find($siteId);

        return $site !== null && (int) $site['organization_id'] === (int) $this->currentOrganizationId();
    }

    private function canAccessTurbine(array $turbine): bool
    {
        return $this->isPlatformAdmin() || $this->siteBelongsToCurrentOrganization((int) $turbine['site_id']);
    }

    private function turbineCodeExists(int $siteId, string $turbineCode, ?int $ignoreId = null): bool
    {
        $builder = $this->model
            ->where('site_id', $siteId)
            ->where('turbine_code', $turbineCode);

        if ($ignoreId !== null) {
            $builder->where('id !=', $ignoreId);
        }

        return $builder->first() !== null;
    }

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

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