<?php

declare(strict_types=1);

namespace App\Http\Controllers\Customer;

use App\Domain\Account\Models\Account;
use App\Domain\Domain\Models\Domain;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Inertia\Inertia;
use Inertia\Response;

/**
 * Email Address Importer (cPanel Address Importer muadili).
 * Bulk CSV upload → parse → confirm → create.
 */
class EmailImporterController extends Controller
{
    public function index(Request $request): Response
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        $available_domains = Domain::where('account_id', $account->id)
            ->whereIn('type', ['main', 'addon'])
            ->pluck('name');

        return Inertia::render('Customer/Email/Importer', [
            'available_domains' => $available_domains,
            'preview' => session('importer_preview'),
        ]);
    }

    public function preview(Request $request): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        $validated = $request->validate([
            'type' => ['required', 'in:account,forwarder'],
            'csv' => ['required', 'string', 'max:100000'],
            'default_domain' => ['required', 'string'],
        ]);

        $type = $validated['type'];
        $raw = $validated['csv'];
        $default_domain = $validated['default_domain'];

        $available_domains = Domain::where('account_id', $account->id)
            ->whereIn('type', ['main', 'addon'])
            ->pluck('name')
            ->map(fn ($d) => mb_strtolower($d))
            ->all();

        $lines = array_filter(
            array_map('trim', preg_split('/\r\n|\r|\n/', $raw)),
            fn ($l) => $l !== ''
        );

        $rows = [];
        $rowNum = 0;

        foreach ($lines as $line) {
            $rowNum++;
            // Skip header line if it starts with "email"
            if ($rowNum === 1 && preg_match('/^\s*email\s*[,;]/i', $line)) {
                continue;
            }

            $cols = preg_split('/[,;]/', $line);
            $cols = array_map('trim', $cols);

            if ($type === 'account') {
                $emailRaw = $cols[0] ?? '';
                $password = $cols[1] ?? '';
                $quota_mb = isset($cols[2]) && is_numeric($cols[2]) ? (int) $cols[2] : 250;

                if ($emailRaw === '') {
                    $rows[] = ['row' => $rowNum, 'email' => '', 'password' => '', 'quota_mb' => $quota_mb, 'status' => 'missing_field', 'message' => 'E-posta alanı boş'];

                    continue;
                }

                // Expand local-only to full address
                if (! str_contains($emailRaw, '@')) {
                    $emailRaw = $emailRaw.'@'.$default_domain;
                }

                if (! filter_var($emailRaw, FILTER_VALIDATE_EMAIL)) {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'password' => $password, 'quota_mb' => $quota_mb, 'status' => 'invalid_email', 'message' => 'Geçersiz e-posta formatı'];

                    continue;
                }

                [$local, $domain] = explode('@', $emailRaw, 2);
                $domain = mb_strtolower($domain);

                if (! in_array($domain, $available_domains, true)) {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'password' => $password, 'quota_mb' => $quota_mb, 'status' => 'invalid_domain', 'message' => "Domain '{$domain}' size ait değil"];

                    continue;
                }

                if (DB::table('email_accounts')->where('local', $local)->where('domain', $domain)->whereNull('deleted_at')->exists()) {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'password' => $password, 'quota_mb' => $quota_mb, 'status' => 'duplicate', 'message' => 'Bu e-posta zaten mevcut'];

                    continue;
                }

                if ($password === '') {
                    $password = Str::random(12);
                }

                $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'local' => $local, 'domain' => $domain, 'password' => $password, 'quota_mb' => $quota_mb, 'status' => 'valid', 'message' => ''];

            } else {
                // forwarder
                $emailRaw = $cols[0] ?? '';
                $forward_to = $cols[1] ?? '';

                if ($emailRaw === '' || $forward_to === '') {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'forward_to' => $forward_to, 'status' => 'missing_field', 'message' => 'E-posta veya hedef adres boş'];

                    continue;
                }

                if (! str_contains($emailRaw, '@')) {
                    $emailRaw = $emailRaw.'@'.$default_domain;
                }

                if (! filter_var($emailRaw, FILTER_VALIDATE_EMAIL)) {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'forward_to' => $forward_to, 'status' => 'invalid_email', 'message' => 'Geçersiz kaynak e-posta formatı'];

                    continue;
                }

                if (! filter_var($forward_to, FILTER_VALIDATE_EMAIL)) {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'forward_to' => $forward_to, 'status' => 'invalid_email', 'message' => 'Geçersiz hedef e-posta formatı'];

                    continue;
                }

                [, $domain] = explode('@', $emailRaw, 2);
                $domain = mb_strtolower($domain);

                if (! in_array($domain, $available_domains, true)) {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'forward_to' => $forward_to, 'status' => 'invalid_domain', 'message' => "Domain '{$domain}' size ait değil"];

                    continue;
                }

                if (DB::table('email_forwarders')->where('source', $emailRaw)->whereNull('deleted_at')->exists()) {
                    $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'forward_to' => $forward_to, 'status' => 'duplicate', 'message' => 'Bu yönlendirme zaten mevcut'];

                    continue;
                }

                $rows[] = ['row' => $rowNum, 'email' => $emailRaw, 'forward_to' => $forward_to, 'status' => 'valid', 'message' => ''];
            }
        }

        session()->flash('importer_preview', [
            'rows' => $rows,
            'type' => $type,
            'default_domain' => $default_domain,
        ]);

        return back();
    }

    public function commit(Request $request): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        $validated = $request->validate([
            'rows' => ['required', 'array'],
            'type' => ['required', 'in:account,forwarder'],
        ]);

        $type = $validated['type'];
        $rows = $validated['rows'];
        $created = 0;
        $skipped = 0;
        $now = now();

        foreach ($rows as $row) {
            if (($row['status'] ?? '') !== 'valid') {
                $skipped++;

                continue;
            }

            if ($type === 'account') {
                $local = $row['local'] ?? '';
                $domain = $row['domain'] ?? '';
                $password = $row['password'] ?? Str::random(12);
                $quota = (int) ($row['quota_mb'] ?? 250);

                if ($local === '' || $domain === '') {
                    $skipped++;

                    continue;
                }

                // Guard against race-condition duplicates
                if (DB::table('email_accounts')->where('local', $local)->where('domain', $domain)->whereNull('deleted_at')->exists()) {
                    $skipped++;

                    continue;
                }

                DB::table('email_accounts')->insert([
                    'account_id' => $account->id,
                    'local' => $local,
                    'domain' => $domain,
                    'password_hash' => password_hash($password, PASSWORD_BCRYPT),
                    'quota_mb' => $quota,
                    'usage_bytes' => 0,
                    'status' => 'pending',
                    'auto_create_dirs' => true,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
                $created++;

            } else {
                $source = $row['email'] ?? '';
                $forward_to = $row['forward_to'] ?? '';

                if ($source === '' || $forward_to === '') {
                    $skipped++;

                    continue;
                }

                if (DB::table('email_forwarders')->where('source', $source)->whereNull('deleted_at')->exists()) {
                    $skipped++;

                    continue;
                }

                DB::table('email_forwarders')->insert([
                    'account_id' => $account->id,
                    'source' => $source,
                    'destinations' => $forward_to,
                    'keep_local_copy' => false,
                    'is_active' => true,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
                $created++;
            }
        }

        return back()->with('success', "{$created} kayıt oluşturuldu, {$skipped} atlandı.");
    }

    public function template(Request $request, string $type): \Illuminate\Http\Response
    {
        if ($type === 'forwarder') {
            $csv = "email,forward_to\ninfo@example.com,destination@gmail.com\n";
            $filename = 'onox-import-template-forwarder.csv';
        } else {
            $csv = "email,password,quota_mb\nuser@example.com,secret123,500\n";
            $filename = 'onox-import-template-account.csv';
        }

        return response($csv)
            ->header('Content-Type', 'text/csv')
            ->header('Content-Disposition', "attachment; filename=\"{$filename}\"");
    }
}
