<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

return new class extends Migration
{
    private array $contacts = [
        [
            'first' => 'Daniel',
            'last' => 'Gioia',
            'email' => 'daniel@gioia.email',
            'uid' => 'kithkin-contact-daniel-gioia',
        ],
        [
            'first' => 'James',
            'last' => 'Gioia',
            'email' => 'james@gioia.email',
            'uid' => 'kithkin-contact-james-gioia',
        ],
    ];

    public function up(): void
    {
        foreach ($this->contacts as $contact) {
            $email = Str::lower($contact['email']);
            $existingId = DB::table('users')->where('email', $email)->value('id');

            if ($existingId) {
                DB::table('users')
                    ->where('id', $existingId)
                    ->update([
                        'uri' => 'principals/' . $email,
                        'firstname' => $contact['first'],
                        'lastname' => $contact['last'],
                        'displayname' => trim($contact['first'] . ' ' . $contact['last']),
                        'timezone' => config('app.timezone', 'UTC'),
                        'email_verified_at' => now(),
                        'updated_at' => now(),
                    ]);
            } else {
                DB::table('users')->insert([
                    'id' => (string) Str::ulid(),
                    'uri' => 'principals/' . $email,
                    'firstname' => $contact['first'],
                    'lastname' => $contact['last'],
                    'displayname' => trim($contact['first'] . ' ' . $contact['last']),
                    'email' => $email,
                    'timezone' => config('app.timezone', 'UTC'),
                    'password' => Hash::make((string) Str::uuid()),
                    'email_verified_at' => now(),
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
            }
        }

        $ownerEmail = Str::lower((string) env('ADMIN_EMAIL', 'admin@example.com'));
        $owner = DB::table('users')->where('email', $ownerEmail)->first();
        if (!$owner) {
            $owner = DB::table('users')->orderBy('created_at')->first();
        }
        if (!$owner) {
            return;
        }

        $principal = $owner->uri ?: ('principals/' . $owner->email);

        $addressbookId = DB::table('addressbooks')
            ->where('principaluri', $principal)
            ->orderBy('id')
            ->value('id');

        if (!$addressbookId) {
            $addressbookId = DB::table('addressbooks')->insertGetId([
                'principaluri' => $principal,
                'uri' => 'default',
                'displayname' => 'Default Address Book',
            ]);

            DB::table('addressbook_meta')->updateOrInsert(
                ['addressbook_id' => $addressbookId],
                [
                    'color' => '#ff40ff',
                    'is_default' => true,
                    'settings' => null,
                    'created_at' => now(),
                    'updated_at' => now(),
                ]
            );
        }

        foreach ($this->contacts as $contact) {
            $email = Str::lower($contact['email']);
            $fn = trim($contact['first'] . ' ' . $contact['last']);
            $uid = $contact['uid'];

            $vcard = "BEGIN:VCARD\r\n"
                . "VERSION:3.0\r\n"
                . "FN:{$fn}\r\n"
                . "EMAIL:{$email}\r\n"
                . "UID:{$uid}\r\n"
                . "END:VCARD\r\n";

            $existingCardId = DB::table('cards')
                ->where('addressbookid', $addressbookId)
                ->where(function ($query) use ($uid, $email) {
                    $query->where('carddata', 'like', '%UID:' . $uid . '%')
                        ->orWhere('carddata', 'like', '%EMAIL:' . $email . '%');
                })
                ->value('id');

            if ($existingCardId) {
                DB::table('cards')
                    ->where('id', $existingCardId)
                    ->update([
                        'lastmodified' => now()->timestamp,
                        'etag' => md5($vcard),
                        'size' => strlen($vcard),
                        'carddata' => $vcard,
                    ]);
                continue;
            }

            DB::table('cards')->insert([
                'addressbookid' => $addressbookId,
                'uri' => (string) Str::uuid() . '.vcf',
                'lastmodified' => now()->timestamp,
                'etag' => md5($vcard),
                'size' => strlen($vcard),
                'carddata' => $vcard,
            ]);
        }
    }

    public function down(): void
    {
        foreach ($this->contacts as $contact) {
            $email = Str::lower($contact['email']);
            $uid = $contact['uid'];

            DB::table('cards')
                ->where(function ($query) use ($uid, $email) {
                    $query->where('carddata', 'like', '%UID:' . $uid . '%')
                        ->orWhere('carddata', 'like', '%EMAIL:' . $email . '%');
                })
                ->delete();

            DB::table('users')
                ->where('email', $email)
                ->delete();
        }
    }
};
