<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Repositories\HouseholdRepository;
use App\Repositories\HouseholderNameRepository;
use Core\Controller;
use Core\Pagination;
use Core\Request;
use Core\Response;
use Core\Validator;

class HouseholderNameController extends Controller
{
    public function index(): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $request     = Request::capture();
        $search      = (string) ($request->input('search') ?? '');
        $householdId = (string) ($request->input('household_id') ?? '');
        $page        = max(1, (int) ($request->input('page') ?? 1));
        $perPage     = 20;

        $repo       = new HouseholderNameRepository(database());
        $total      = $repo->countAll($search, $householdId);
        $pagination = new Pagination($total, $page, $perPage);
        $names      = $repo->findPaged($page, $perPage, $search, $householdId);

        return $this->view('householder-names.index', [
            'pageTitle'  => 'Householder Names',
            'names'      => $names,
            'search'     => $search,
            'householdId' => $householdId,
            'pagination' => $pagination,
        ]);
    }

    public function show(int|string $id): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $name = (new HouseholderNameRepository(database()))->findWithHousehold((int) $id);

        if (!$name) {
            return Response::notFound('Householder name not found.');
        }

        return $this->view('householder-names.show', [
            'pageTitle' => e($name['name']),
            'name'      => $name,
        ]);
    }

    public function create(): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $request    = Request::capture();
        $households = (new HouseholdRepository(database()))->all();

        return $this->view('householder-names.create', [
            'pageTitle'          => 'New Householder Name',
            'households'         => $households,
            'defaultHouseholdId' => (string) ($request->input('household_id') ?? ''),
            'errors'             => [],
            'old'                => [],
        ]);
    }

    public function store(): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $request    = Request::capture();
        $households = (new HouseholdRepository(database()))->all();

        if (!verify_csrf_token($request->input('_token'))) {
            return $this->view('householder-names.create', [
                'pageTitle'          => 'New Householder Name',
                'households'         => $households,
                'defaultHouseholdId' => '',
                'errors'             => ['_token' => ['Invalid request. Please try again.']],
                'old'                => $request->all(),
            ]);
        }

        $householdId    = (string) ($request->input('household_id') ?? '');
        $name           = trim((string) ($request->input('name') ?? ''));
        $letterReturned = (int) (bool) $request->input('letter_returned');
        $returnDate     = trim((string) ($request->input('return_date') ?? '')) ?: null;

        $validator = (new Validator())
            ->required('household_id', $householdId, 'Household is required.')
            ->required('name', $name, 'Name is required.')
            ->maxLength('name', $name, 255);

        if ($validator->fails()) {
            return $this->view('householder-names.create', [
                'pageTitle'          => 'New Householder Name',
                'households'         => $households,
                'defaultHouseholdId' => $householdId,
                'errors'             => $validator->errors(),
                'old'                => $request->all(),
            ]);
        }

        $now = date('Y-m-d H:i:s');
        database()->execute(
            'INSERT INTO householder_names (household_id, name, letter_returned, return_date, created_at, updated_at)
             VALUES (:household_id, :name, :letter_returned, :return_date, :now, :now)',
            ['household_id' => $householdId, 'name' => $name,
             'letter_returned' => $letterReturned, 'return_date' => $returnDate, 'now' => $now]
        );

        flash('success', "Householder name \"{$name}\" created.");
        return $this->redirect('/householder-names');
    }

    public function edit(int|string $id): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $name = (new HouseholderNameRepository(database()))->find((int) $id);

        if (!$name) {
            return Response::notFound('Householder name not found.');
        }

        $households = (new HouseholdRepository(database()))->all();

        return $this->view('householder-names.edit', [
            'pageTitle'  => 'Edit Householder Name',
            'name'       => $name,
            'households' => $households,
            'errors'     => [],
        ]);
    }

    public function update(int|string $id): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $request = Request::capture();
        $repo    = new HouseholderNameRepository(database());
        $name    = $repo->find((int) $id);

        if (!$name) {
            return Response::notFound('Householder name not found.');
        }

        if (!verify_csrf_token($request->input('_token'))) {
            flash('error', 'Invalid request.');
            return $this->redirect('/householder-names/' . $id . '/edit');
        }

        $householdId    = (string) ($request->input('household_id') ?? '');
        $nameVal        = trim((string) ($request->input('name') ?? ''));
        $letterReturned = (int) (bool) $request->input('letter_returned');
        $returnDate     = trim((string) ($request->input('return_date') ?? '')) ?: null;

        $validator = (new Validator())
            ->required('household_id', $householdId, 'Household is required.')
            ->required('name', $nameVal, 'Name is required.')
            ->maxLength('name', $nameVal, 255);

        $households = (new HouseholdRepository(database()))->all();

        if ($validator->fails()) {
            return $this->view('householder-names.edit', [
                'pageTitle'  => 'Edit Householder Name',
                'name'       => array_merge($name, ['name' => $nameVal, 'household_id' => $householdId]),
                'households' => $households,
                'errors'     => $validator->errors(),
            ]);
        }

        database()->execute(
            'UPDATE householder_names SET household_id = :household_id, name = :name,
             letter_returned = :letter_returned, return_date = :return_date,
             updated_at = :now WHERE id = :id',
            ['household_id' => $householdId, 'name' => $nameVal, 'letter_returned' => $letterReturned,
             'return_date' => $returnDate, 'now' => date('Y-m-d H:i:s'), 'id' => $id]
        );

        flash('success', "Householder name \"{$nameVal}\" updated.");
        return $this->redirect('/householder-names/' . $id);
    }

    public function delete(int|string $id): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $request = Request::capture();
        $name    = (new HouseholderNameRepository(database()))->find((int) $id);

        if (!$name) {
            return Response::notFound('Householder name not found.');
        }

        if (!verify_csrf_token($request->input('_token'))) {
            flash('error', 'Invalid request.');
            return $this->redirect('/householder-names');
        }

        $householdId = $name['household_id'];
        database()->execute('DELETE FROM householder_names WHERE id = :id', ['id' => $id]);

        flash('success', 'Householder name deleted.');
        return $this->redirect('/households/' . $householdId);
    }

    public function markReturned(int|string $id): Response
    {
        if ($redirect = $this->requireAuth()) {
            return $redirect;
        }

        $request = Request::capture();
        $repo    = new HouseholderNameRepository(database());
        $name    = $repo->find((int) $id);

        if (!$name) {
            return Response::notFound('Householder name not found.');
        }

        if (!verify_csrf_token($request->input('_token'))) {
            flash('error', 'Invalid request.');
            return $this->redirect('/households/' . $name['household_id']);
        }

        $repo->toggleLetterReturned((int) $id);

        flash('success', 'Letter returned status updated.');
        return $this->redirect('/households/' . $name['household_id']);
    }
}
