<?php

namespace Modules\Contracts\Controllers;

use App\Controllers\BaseController;
use App\Models\CompanyModel;
use App\Models\CustomerGroupModel;
use App\Models\CustomerSiteModel;
use Modules\Contracts\Services\CustomerService;

class CustomerController extends BaseController
{
    protected CompanyModel $companies;
    protected CustomerGroupModel $groups;
    protected CustomerSiteModel $sites;
    protected CustomerService $service;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->companies = new CompanyModel();
        $this->groups    = new CustomerGroupModel();
        $this->sites     = new CustomerSiteModel();
        $this->service   = new CustomerService();
    }

    public function index()
    {
        $search       = trim((string) $this->request->getGet('q'));
        $status       = $this->request->getGet('status') ?: null;
        $groupId      = $this->request->getGet('group_id') ?: null;
        $siteId       = $this->request->getGet('site_id') ?: null;
        $customerType = $this->request->getGet('customer_type') ?: null;
        $oneTimeRaw   = $this->request->getGet('is_one_time');
        $isOneTime    = ($oneTimeRaw === '0' || $oneTimeRaw === '1') ? (int) $oneTimeRaw : null;

        $companies = $this->companies
            ->scopeForList(
                $search ?: null,
                $status,
                $groupId ? (int) $groupId : null,
                $customerType,
                $isOneTime,
                $siteId ? (int) $siteId : null
            )
            ->orderBy('name', 'ASC')
            ->paginate(20);

        return view('Modules\Contracts\Views\customers\index', array_merge($this->baseViewData(), [
            'title'     => 'Customers',
            'companies' => $companies,
            'pager'     => $this->companies->pager,
            'groups'    => $this->groups->getActive(),
            'sites'     => $this->sites->getActive($search !== '' ? $search : null, 100),
            'groupMap'  => $this->buildGroupMap(),
            'siteMap'   => $this->buildSiteMap($companies),
            'filters'   => [
                'search'       => $search,
                'status'       => $status,
                'groupId'      => $groupId,
                'siteId'       => $siteId,
                'customerType' => $customerType,
                'isOneTime'    => $oneTimeRaw,
            ],
        ]));
    }

    public function createForm()
    {
        $prefillSiteId = $this->request->getGet('site_id');

        return view('Modules\Contracts\Views\customers\create', array_merge($this->baseViewData(), [
            'title'  => 'Add Customer',
            'groups' => $this->groups->getActive(),
            'sites'  => $this->sites->getActive(null, 100),
            'company'=> $prefillSiteId ? ['site_id' => (int) $prefillSiteId] : [],
        ]));
    }

    public function store()
    {
        if (! $this->validate([
            'name'          => 'required|min_length[2]|max_length[150]',
            'email'         => 'permit_empty|valid_email',
            'customer_type' => 'required|in_list[product,service,project]',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $result = $this->service->create($this->request->getPost(), (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->withInput()->with('errors', $result['errors']);
        }

        return redirect()->to('/contracts/customers/' . $result['id'])->with('success', 'Customer created.');
    }

    public function show(int $id)
    {
        $company = $this->companies->find($id);
        if (! $company) {
            return redirect()->to('/contracts/customers')->with('error', 'Customer not found.');
        }

        $group = $company['customer_group_id'] ? $this->groups->find($company['customer_group_id']) : null;
        $site  = $company['site_id'] ? $this->sites->find($company['site_id']) : null;

        return view('Modules\Contracts\Views\customers\show', array_merge($this->baseViewData(), [
            'title'   => $company['name'],
            'company' => $company,
            'group'   => $group,
            'site'    => $site,
        ]));
    }

    public function editForm(int $id)
    {
        $company = $this->companies->find($id);
        if (! $company) {
            return redirect()->to('/contracts/customers')->with('error', 'Customer not found.');
        }

        return view('Modules\Contracts\Views\customers\edit', array_merge($this->baseViewData(), [
            'title'   => 'Edit Customer',
            'company' => $company,
            'groups'  => $this->groups->getActive(),
            'sites'   => $this->sites->getActive(null, 100),
        ]));
    }

    public function update(int $id)
    {
        if (! $this->validate([
            'name'          => 'required|min_length[2]|max_length[150]',
            'email'         => 'permit_empty|valid_email',
            'customer_type' => 'required|in_list[product,service,project]',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $result = $this->service->update($id, $this->request->getPost(), (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->withInput()->with('errors', $result['errors']);
        }

        return redirect()->to('/contracts/customers/' . $id)->with('success', 'Customer updated.');
    }

    public function activate(int $id)
    {
        $this->service->activate($id, (int) $this->session->get('user_id'));

        return redirect()->back()->with('success', 'Customer activated.');
    }

    public function deactivate(int $id)
    {
        $this->service->deactivate($id, (int) $this->session->get('user_id'));

        return redirect()->back()->with('success', 'Customer deactivated.');
    }

    public function destroy(int $id)
    {
        $result = $this->service->delete($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->to('/contracts/customers')->with('error', $result['error']);
        }

        return redirect()->to('/contracts/customers')->with('success', 'Customer deleted.');
    }

    protected function buildGroupMap(): array
    {
        $map = [];
        foreach ($this->groups->findAll() as $g) {
            $map[$g['id']] = $g['name'];
        }

        return $map;
    }

    protected function buildSiteMap(array $companies = []): array
    {
        $siteIds = array_values(array_unique(array_filter(array_map(
            static fn (array $company): int => (int) ($company['site_id'] ?? 0),
            $companies
        ))));

        if ($siteIds === []) {
            return [];
        }

        $map = [];
        foreach ($this->sites->whereIn('id', $siteIds)->findAll() as $s) {
            $map[$s['id']] = $s['name'];
        }

        return $map;
    }
}
