<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\BaseController;
use App\Core\Database;
use App\Core\Request;
use App\Core\Response;
use App\Helpers\AjaxResponse;
use App\Services\ActivityLogger;

/**
 * BusinessLineSettingsController
 *
 * Where each company (Homecare, Cleaner) fills in the details that
 * MailService/EmailSignatureService automatically append to every
 * outbound email (campaign, automation, or personal) sent under it —
 * phone, website, social links, physical mailing address, and logo.
 * The address specifically matters for CASL/CAN-SPAM compliance and
 * inbox deliverability, not just appearance.
 *
 * Logo uploads deliberately do NOT use UploadHelper/the app's normal
 * /uploads directory — that directory is permission-gated and served
 * only through an authenticated controller, which works for internal
 * attachments but is exactly wrong for a signature logo: email
 * clients (Gmail, Outlook, etc.) fetch signature images with zero
 * session or credentials. Logos are stored under public/uploads-
 * public/logos instead — plain static files, no auth, same finfo
 * real-content-type security discipline as the rest of the app's
 * uploads, just image types only and a small size cap.
 */
final class BusinessLineSettingsController extends BaseController
{
    public function show(Request $request): Response
    {
        $rows = Database::connection()->query('SELECT * FROM business_lines ORDER BY name')->fetchAll();

        return $this->view('settings/business-lines', [
            'title' => 'Company Details',
            'activeNav' => 'business-line-settings',
            'breadcrumbs' => [['Home', 'dashboard'], ['Settings', 'settings/business-lines'], ['Company Details', 'settings/business-lines']],
            'businessLines' => $rows,
        ]);
    }

    public function update(Request $request): Response
    {
        $data = $this->validateOrFail($request, [
            'business_line_id' => 'required|integer|exists:business_lines,id',
            'legal_name' => 'nullable|string|max:191',
            'support_phone' => 'nullable|string|max:30',
            'support_email' => 'nullable|email|max:191',
            'website' => 'nullable|url|max:191',
            'address_line1' => 'nullable|string|max:191',
            'city' => 'nullable|string|max:120',
            'province' => 'nullable|string|max:120',
            'postal_code' => 'nullable|string|max:20',
            'facebook_url' => 'nullable|url|max:191',
            'instagram_url' => 'nullable|url|max:191',
            'linkedin_url' => 'nullable|url|max:191',
            'tiktok_url' => 'nullable|url|max:191',
        ]);

        $businessLineId = $data['business_line_id'];
        unset($data['business_line_id']);

        $set = implode(', ', array_map(fn ($col) => "{$col} = :{$col}", array_keys($data)));
        $data['id'] = $businessLineId;

        Database::connection()
            ->prepare("UPDATE business_lines SET {$set}, updated_at = NOW() WHERE id = :id")
            ->execute($data);

        ActivityLogger::logAction('Updated company details for business line #' . $businessLineId, 'admin');

        return AjaxResponse::success(null, 'Company details saved.');
    }

    public function uploadLogo(Request $request): Response
    {
        $businessLineId = (int) $request->input('business_line_id');
        $stmt = Database::connection()->prepare('SELECT id FROM business_lines WHERE id = :id');
        $stmt->execute(['id' => $businessLineId]);
        if ($stmt->fetchColumn() === false) {
            return AjaxResponse::error('Business line not found.', 422);
        }

        $file = $request->file('logo');
        if ($file === null || ($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
            return AjaxResponse::error('No logo file was uploaded.', 422);
        }

        if (!is_uploaded_file($file['tmp_name'])) {
            return AjaxResponse::error('Invalid upload.', 422);
        }

        $maxBytes = 2 * 1024 * 1024; // 2MB — a signature logo, not a hero image
        if ($file['size'] > $maxBytes) {
            return AjaxResponse::error('Logo must be under 2MB.', 422);
        }

        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $realMime = finfo_file($finfo, $file['tmp_name']) ?: 'application/octet-stream';
        finfo_close($finfo);

        $allowed = ['image/png' => 'png', 'image/jpeg' => 'jpg', 'image/webp' => 'webp'];
        // SVG is deliberately excluded — it can embed <script>, and this
        // directory is served publicly with no further checks.
        if (!isset($allowed[$realMime])) {
            return AjaxResponse::error('Logo must be a PNG, JPEG, or WebP image.', 422);
        }

        $publicDir = dirname(__DIR__, 2) . '/public/uploads-public/logos';
        if (!is_dir($publicDir) && !mkdir($publicDir, 0755, true) && !is_dir($publicDir)) {
            return AjaxResponse::error('Could not create the upload directory.', 500);
        }

        $filename = 'bl' . $businessLineId . '-' . bin2hex(random_bytes(12)) . '.' . $allowed[$realMime];
        $targetPath = $publicDir . '/' . $filename;

        if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
            return AjaxResponse::error('The logo could not be saved.', 500);
        }
        chmod($targetPath, 0644);

        $logoUrl = base_url('uploads-public/logos/' . $filename);

        Database::connection()
            ->prepare('UPDATE business_lines SET logo_url = :url, updated_at = NOW() WHERE id = :id')
            ->execute(['url' => $logoUrl, 'id' => $businessLineId]);

        ActivityLogger::logAction('Uploaded logo for business line #' . $businessLineId, 'admin');

        return AjaxResponse::success(['logo_url' => $logoUrl], 'Logo uploaded.');
    }
}
