<?php

namespace App\Controllers;

use App\Models\OrganizationModel;
use App\Models\SiteModel;

class Sites extends BaseController
{
    private SiteModel $model;
    private OrganizationModel $organizations;

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

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

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

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

        return view('sites/index', [
            'title' => 'Sites',
            'active' => 'sites',
            'sites' => $query->orderBy('sites.name', 'ASC')->findAll(),
        ]);
    }

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

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

        return view('sites/form', [
            'title' => 'Novo site',
            'active' => 'sites',
            'site' => null,
            'organizations' => $this->organizationOptions(),
            'action' => site_url('sites'),
            'isPlatformAdmin' => $this->isPlatformAdmin(),
        ]);
    }

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

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

        if ($this->siteCodeExists($data['organization_id'], $data['site_code'])) {
            return redirect()->back()->withInput()->with('error', 'Ja existe um site com esse codigo nesta organizacao.');
        }

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

        return redirect()->to(site_url('sites'))->with('success', 'Site criado com sucesso.');
    }

    public function edit(int $id)
    {
        $site = $this->model->find($id);
        if (! $site || ! $this->canAccessSite($site)) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound('Site nao encontrado.');
        }

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

        return view('sites/form', [
            'title' => 'Editar site',
            'active' => 'sites',
            'site' => $site,
            'organizations' => $this->organizationOptions(),
            'action' => site_url('sites/' . $id),
            'isPlatformAdmin' => $this->isPlatformAdmin(),
        ]);
    }

    public function update(int $id)
    {
        $site = $this->model->find($id);
        if (! $site || ! $this->canAccessSite($site)) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound('Site nao encontrado.');
        }

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

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

        if ($this->siteCodeExists($data['organization_id'], $data['site_code'], $id)) {
            return redirect()->back()->withInput()->with('error', 'Ja existe um site com esse codigo nesta organizacao.');
        }

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

        return redirect()->to(site_url('sites'))->with('success', 'Site atualizado com sucesso.');
    }

    public function delete(int $id)
    {
        $site = $this->model->find($id);
        if (! $site || ! $this->canAccessSite($site)) {
            return redirect()->to(site_url('sites'))->with('error', 'Site nao encontrado.');
        }

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

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

        return redirect()->to(site_url('sites'))->with('success', 'Site removido com sucesso.');
    }

    private function collectData(): array
    {
        $organizationId = $this->isPlatformAdmin()
            ? (int) $this->request->getPost('organization_id')
            : (int) $this->currentOrganizationId();

        return [
            'organization_id' => $organizationId,
            'name' => trim((string) $this->request->getPost('name')),
            'site_code' => trim((string) $this->request->getPost('site_code')),
            'site_type' => trim((string) $this->request->getPost('site_type')) ?: 'wind_farm',
            'country_code' => strtoupper(trim((string) $this->request->getPost('country_code'))) ?: null,
            'region' => trim((string) $this->request->getPost('region')) ?: null,
            'location' => trim((string) $this->request->getPost('location')) ?: null,
            'latitude' => $this->nullableDecimal($this->request->getPost('latitude')),
            'longitude' => $this->nullableDecimal($this->request->getPost('longitude')),
            'commissioned_at' => trim((string) $this->request->getPost('commissioned_at')) ?: null,
            'status' => trim((string) $this->request->getPost('status')) ?: 'active',
        ];
    }

    private function rules(): array
    {
        return [
            'organization_id' => 'required|integer',
            'name' => 'required|min_length[3]|max_length[160]',
            'site_code' => 'required|max_length[80]',
            'site_type' => 'required|in_list[wind_farm,site,substation,service_hub]',
            'country_code' => 'permit_empty|exact_length[2]',
            'region' => 'permit_empty|max_length[80]',
            'location' => 'permit_empty|max_length[190]',
            'latitude' => 'permit_empty|decimal',
            'longitude' => 'permit_empty|decimal',
            'commissioned_at' => 'permit_empty|valid_date[Y-m-d]',
            'status' => 'required|in_list[active,inactive,pending,maintenance]',
        ];
    }

    private function organizationOptions(): array
    {
        if ($this->isPlatformAdmin()) {
            return $this->organizations->orderBy('name', 'ASC')->findAll();
        }

        return $this->organizations->where('id', (int) $this->currentOrganizationId())->findAll();
    }

    private function siteCodeExists(int $organizationId, string $siteCode, ?int $ignoreId = null): bool
    {
        $builder = $this->model
            ->where('organization_id', $organizationId)
            ->where('site_code', $siteCode);

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

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

    private function canAccessSite(array $site): bool
    {
        return $this->isPlatformAdmin() || (int) $site['organization_id'] === (int) $this->currentOrganizationId();
    }

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

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