<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Services\MailService;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Illuminate\Database\Capsule\Manager as DB;

class ContactController
{
    use ControllerTrait;

    public function index(Request $request, Response $response): Response
    {
        $guard = $this->requireRole($request, $response, ['admin_fab', 'super_admin']);
        if ($guard) return $guard;

        $params = $request->getQueryParams();
        [$page, $limit, $offset] = $this->paginate($request);

        try {
            $query = DB::connection('workflow')->table('contacts')
                ->where('actif', 1)
                ->orderByRaw('est_mko_interne DESC, nom ASC');

            if (!empty($params['categorie'])) {
                $query->whereJsonContains('categories', $params['categorie']);
            }
            if (!empty($params['search'])) {
                $s = $params['search'];
                $query->where(function ($q) use ($s) {
                    $q->where('nom', 'like', "%{$s}%")
                      ->orWhere('email', 'like', "%{$s}%")
                      ->orWhere('ville', 'like', "%{$s}%");
                });
            }

            $total    = $query->count();
            $contacts = $query->skip($offset)->take($limit)->get();

            return $this->successList($response, $contacts->toArray(), ['page' => $page, 'limit' => $limit, 'total' => $total]);
        } catch (\Exception $e) {
            return $this->success($response, []);
        }
    }

    public function fabricants(Request $request, Response $response): Response
    {
        try {
            $contacts = DB::connection('workflow')->table('contacts')
                ->where('actif', 1)
                ->where('peut_fabriquer', 1)
                ->orderByRaw('est_mko_interne DESC, nom ASC')
                ->get();
            return $this->success($response, $contacts->toArray());
        } catch (\Exception $e) {
            return $this->success($response, []);
        }
    }

    public function graveurs(Request $request, Response $response): Response
    {
        try {
            $contacts = DB::connection('workflow')->table('contacts')
                ->where('actif', 1)
                ->where('peut_graver', 1)
                ->orderByRaw('est_mko_interne DESC, nom ASC')
                ->get();
            return $this->success($response, $contacts->toArray());
        } catch (\Exception $e) {
            return $this->success($response, []);
        }
    }

    public function create(Request $request, Response $response): Response
    {
        $guard = $this->requireRole($request, $response, ['admin_fab', 'super_admin']);
        if ($guard) return $guard;

        $body = (array)$request->getParsedBody();
        try {
            if (isset($body['categories']) && is_array($body['categories'])) {
                $body['categories'] = json_encode($body['categories']);
            }
            $body['created_at'] = date('Y-m-d H:i:s');
            $id = DB::connection('workflow')->table('contacts')->insertGetId($body);
            return $this->success($response, ['id' => $id], 201);
        } catch (\Exception $e) {
            return $this->error($response, 'INTERNAL_ERROR', $e->getMessage(), 500);
        }
    }

    public function update(Request $request, Response $response, array $args): Response
    {
        $guard = $this->requireRole($request, $response, ['admin_fab', 'super_admin']);
        if ($guard) return $guard;

        $body = (array)$request->getParsedBody();
        try {
            if (isset($body['categories']) && is_array($body['categories'])) {
                $body['categories'] = json_encode($body['categories']);
            }
            $body['updated_at'] = date('Y-m-d H:i:s');
            DB::connection('workflow')->table('contacts')->where('id', (int)$args['id'])->update($body);
            return $this->success($response, ['id' => (int)$args['id']]);
        } catch (\Exception $e) {
            return $this->error($response, 'INTERNAL_ERROR', $e->getMessage(), 500);
        }
    }

    public function archive(Request $request, Response $response, array $args): Response
    {
        $guard = $this->requireRole($request, $response, ['super_admin']);
        if ($guard) return $guard;

        try {
            DB::connection('workflow')->table('contacts')
                ->where('id', (int)$args['id'])
                ->update(['actif' => 0]);
            return $this->success($response, ['message' => 'Contact archivé']);
        } catch (\Exception $e) {
            return $this->error($response, 'INTERNAL_ERROR', $e->getMessage(), 500);
        }
    }

    public function creerAccesFab(Request $request, Response $response, array $args): Response
    {
        $guard = $this->requireRole($request, $response, ['admin_fab', 'super_admin']);
        if ($guard) return $guard;

        try {
            $contactId = (int)$args['id'];
            $contact   = DB::connection('workflow')->table('contacts')->find($contactId);
            if (!$contact) return $this->error($response, 'NOT_FOUND', 'Contact introuvable', 404);

            $body      = (array)$request->getParsedBody();
            $role      = $body['role'] ?? 'operateur_fab';
            $atelierId = $contact->atelier_id;
            $password  = bin2hex(random_bytes(6));

            $existing = DB::table('users')->where('email', $contact->email)->first();
            if ($existing) {
                return $this->error($response, 'CONFLICT', 'Un compte existe déjà pour cet email', 409);
            }

            $userId = DB::table('users')->insertGetId([
                'email'            => $contact->email,
                'password'         => password_hash($password, PASSWORD_BCRYPT),
                'prenom'           => $contact->prenom ?? $contact->nom,
                'nom'              => $contact->nom,
                'role'             => $role,
                'atelier_id'       => $atelierId,
                'actif'            => 1,
                'date_inscription' => date('Y-m-d H:i:s'),
            ]);

            DB::connection('workflow')->table('contacts')
                ->where('id', $contactId)
                ->update(['user_id' => $userId]);

            $mail = new MailService();
            $mail->accesFabCree($contact->email, $contact->prenom ?? $contact->nom, $password);

            return $this->success($response, ['user_id' => $userId, 'email' => $contact->email]);
        } catch (\Exception $e) {
            return $this->error($response, 'INTERNAL_ERROR', $e->getMessage(), 500);
        }
    }

    public function operateurs(Request $request, Response $response, array $args): Response
    {
        $guard = $this->requireRole($request, $response, ['admin_fab', 'super_admin']);
        if ($guard) return $guard;

        try {
            $operateurs = DB::connection('workflow')->table('contacts')
                ->where('fabricant_contact_id', (int)$args['id'])
                ->whereJsonContains('categories', 'operateur')
                ->get();
            return $this->success($response, $operateurs->toArray());
        } catch (\Exception $e) {
            return $this->success($response, []);
        }
    }
}
