<?php

namespace App\Controllers\Api\V1;

use App\Controllers\BaseController;
use App\Services\Job\JobService;

class JobController extends BaseController
{
    private JobService $jobs;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->jobs = new JobService();
    }

    // --- Public ---

    public function index()
    {
        $filters = $this->request->getGet() ?? [];
        $page = (int) ($filters['page'] ?? 1);
        $perPage = min(100, (int) ($filters['per_page'] ?? 20));

        $jobs = $this->jobs->searchPublic($filters, $page, $perPage);

        return $this->jsonSuccess(array_map(fn ($j) => $j->toArray(), $jobs), ['page' => $page, 'per_page' => $perPage]);
    }

    public function show(string $slug)
    {
        try {
            $job = $this->jobs->viewPublicBySlug($slug);
        } catch (\RuntimeException $e) {
            return $this->jsonError([['code' => 'NOT_FOUND', 'message' => $e->getMessage()]], 404);
        }

        return $this->jsonSuccess(['job' => $job]);
    }

    // --- Agency (authenticated + tenant-scoped) ---

    public function mine()
    {
        $user = $this->currentUser();
        $status = $this->request->getGet('status');
        $jobs = $this->jobs->listForAgency($user->agency_id, $status ?: null);
        return $this->jsonSuccess($jobs);
    }

    /**
     * Bulk job posting from a CSV upload. Parsed with PHP's native
     * fgetcsv() rather than any Composer CSV library — deliberately, since
     * this must work in the Composer-less shared-hosting build too.
     */
    public function bulkUpload()
    {
        $user = $this->currentUser();
        $file = $this->request->getFile('csv');

        if (! $file || ! $file->isValid()) {
            return $this->jsonError([['code' => 'NO_FILE', 'message' => 'Please attach a CSV file.']], 422);
        }
        if (strtolower($file->getClientExtension()) !== 'csv') {
            return $this->jsonError([['code' => 'INVALID_FILE_TYPE', 'message' => 'File must be a .csv file.']], 422);
        }

        $handle = fopen($file->getTempName(), 'r');
        if (! $handle) {
            return $this->jsonError([['code' => 'READ_ERROR', 'message' => 'Could not read the uploaded file.']], 422);
        }

        $header = fgetcsv($handle);
        if (! $header) {
            fclose($handle);
            return $this->jsonError([['code' => 'EMPTY_FILE', 'message' => 'The CSV file appears to be empty.']], 422);
        }
        $header = array_map(fn ($h) => strtolower(trim($h)), $header);

        $rows = [];
        while (($line = fgetcsv($handle)) !== false) {
            if (count(array_filter($line, fn ($v) => trim((string) $v) !== '')) === 0) {
                continue; // skip fully blank rows
            }
            // Pad/truncate to header length so a short row doesn't shift
            // columns for every row after it.
            $line = array_pad(array_slice($line, 0, count($header)), count($header), null);
            $rows[] = array_combine($header, $line);
        }
        fclose($handle);

        if (empty($rows)) {
            return $this->jsonError([['code' => 'NO_ROWS', 'message' => 'No data rows found after the header.']], 422);
        }
        if (count($rows) > 200) {
            return $this->jsonError([['code' => 'TOO_MANY_ROWS', 'message' => 'Maximum 200 jobs per upload.']], 422);
        }

        $results = $this->jobs->bulkCreate($user->agency_id, $user->id, $rows);

        return $this->jsonSuccess($results);
    }

    public function create()
    {
        $user = $this->currentUser();

        $rules = [
            'title'       => 'required|max_length[200]',
            'description' => 'required|min_length[50]',
        ];
        if (! $this->validate($rules)) {
            return $this->jsonValidationError($this->validator->getErrors());
        }

        try {
            $job = $this->jobs->create($user->agency_id, $user->id, $this->request->getJSON(true));
        } catch (\App\Exceptions\PlanLimitExceededException $e) {
            return $this->jsonError([['code' => 'PLAN_LIMIT_EXCEEDED', 'message' => $e->getMessage()]], 403);
        }

        return $this->jsonSuccess(['job' => $job], [], 201);
    }

    public function update(int $id)
    {
        $user = $this->currentUser();

        try {
            $job = $this->jobs->update($user->agency_id, $id, $this->request->getJSON(true), $user->id);
        } catch (\RuntimeException $e) {
            return $this->jsonError([['code' => 'NOT_FOUND', 'message' => $e->getMessage()]], 404);
        }

        return $this->jsonSuccess(['job' => $job]);
    }

    public function publish(int $id)
    {
        $user = $this->currentUser();

        try {
            $job = $this->jobs->publish($user->agency_id, $id, $user->id);
        } catch (\RuntimeException $e) {
            return $this->jsonError([['code' => 'NOT_FOUND', 'message' => $e->getMessage()]], 404);
        }

        return $this->jsonSuccess(['job' => $job]);
    }

    public function close(int $id)
    {
        $user = $this->currentUser();

        try {
            $job = $this->jobs->close($user->agency_id, $id, $user->id);
        } catch (\RuntimeException $e) {
            return $this->jsonError([['code' => 'NOT_FOUND', 'message' => $e->getMessage()]], 404);
        }

        return $this->jsonSuccess(['job' => $job]);
    }

    public function delete(int $id)
    {
        $user = $this->currentUser();

        try {
            $this->jobs->delete($user->agency_id, $id, $user->id);
        } catch (\RuntimeException $e) {
            return $this->jsonError([['code' => 'NOT_FOUND', 'message' => $e->getMessage()]], 404);
        }

        return $this->jsonSuccess(['message' => 'Job deleted.']);
    }
}
