<?php
declare(strict_types=1);

namespace App\Models;

use PDO;

class Artist extends BaseModel
{
    protected string $table = 'artists';

    public function forUser(int $userId): ?array
    {
        $statement = $this->db()->prepare('SELECT * FROM artists WHERE user_id = :user_id ORDER BY id DESC LIMIT 1');
        $statement->execute(['user_id' => $userId]);
        $row = $statement->fetch();

        return $row ?: null;
    }

    public function approvedForUser(int $userId): ?array
    {
        $artist = $this->forUser($userId);
        if (!$artist) {
            return null;
        }

        $status = (string) ($artist['status'] ?? (!empty($artist['verified']) ? 'approved' : 'pending'));

        return $status === 'approved' ? $artist : null;
    }

    public function upsertApplication(int $userId, array $input): array
    {
        $name = trim((string) ($input['artist_name'] ?? ''));
        $slug = $this->slugify((string) ($input['slug'] ?? $name));
        $bio = trim((string) ($input['bio'] ?? ''));

        if ($name === '' || $slug === '' || $bio === '') {
            throw new \InvalidArgumentException('Sanatci adi, slug ve bio zorunludur.');
        }

        if (empty($input['rights_confirmed'])) {
            throw new \InvalidArgumentException('Hak sahipligi onayini isaretlemelisin.');
        }

        $existing = $this->forUser($userId);
        $this->assertSlugAvailable($slug, $existing ? (int) $existing['id'] : null);

        $data = [
            'user_id' => $userId,
            'artist_name' => substr($name, 0, 160),
            'slug' => substr($slug, 0, 180),
            'bio' => $bio,
            'avatar' => trim((string) ($input['avatar'] ?? ($existing['avatar'] ?? ''))) ?: null,
            'cover_image' => trim((string) ($input['cover_image'] ?? ($existing['cover_image'] ?? ''))) ?: null,
            'spotify_url' => $this->cleanUrl((string) ($input['spotify_url'] ?? '')),
            'youtube_url' => $this->cleanUrl((string) ($input['youtube_url'] ?? '')),
            'apple_music_url' => $this->cleanUrl((string) ($input['apple_music_url'] ?? '')),
            'instagram_url' => $this->cleanUrl((string) ($input['instagram_url'] ?? '')),
        ];

        if ($existing) {
            $statement = $this->db()->prepare(
                'UPDATE artists
                 SET artist_name = :artist_name,
                     slug = :slug,
                     bio = :bio,
                     avatar = :avatar,
                     cover_image = :cover_image,
                     spotify_url = :spotify_url,
                     youtube_url = :youtube_url,
                     apple_music_url = :apple_music_url,
                     instagram_url = :instagram_url,
                     status = "pending",
                     verified = 0,
                     rejection_reason = NULL,
                     rights_confirmed_at = COALESCE(rights_confirmed_at, NOW()),
                     updated_at = NOW()
                 WHERE id = :id AND user_id = :user_id'
            );
            $statement->execute($data + ['id' => (int) $existing['id']]);

            return $this->forUser($userId) ?: [];
        }

        $statement = $this->db()->prepare(
            'INSERT INTO artists
                (user_id, artist_name, slug, bio, avatar, cover_image, verified, status, rejection_reason,
                 spotify_url, youtube_url, apple_music_url, instagram_url, rights_confirmed_at, created_at, updated_at)
             VALUES
                (:user_id, :artist_name, :slug, :bio, :avatar, :cover_image, 0, "pending", NULL,
                 :spotify_url, :youtube_url, :apple_music_url, :instagram_url, NOW(), NOW(), NOW())'
        );
        $statement->execute($data);

        return $this->forUser($userId) ?: [];
    }

    public function listForAdmin(array $filters = [], int $limit = 120): array
    {
        $limit = min(max($limit, 1), 300);
        $where = [];
        $params = [];
        if (!empty($filters['status'])) {
            $where[] = 'a.status = :status';
            $params['status'] = (string) $filters['status'];
        }
        if (!empty($filters['q'])) {
            $where[] = '(a.artist_name LIKE :q_name OR a.slug LIKE :q_slug OR u.username LIKE :q_user)';
            $like = '%' . trim((string) $filters['q']) . '%';
            $params['q_name'] = $like;
            $params['q_slug'] = $like;
            $params['q_user'] = $like;
        }

        $sql = 'SELECT a.*, u.username, u.email
                FROM artists a
                LEFT JOIN users u ON u.id = a.user_id';
        if ($where !== []) {
            $sql .= ' WHERE ' . implode(' AND ', $where);
        }
        $sql .= ' ORDER BY FIELD(a.status, "pending", "rejected", "approved"), a.updated_at DESC, a.id DESC LIMIT :limit';

        $statement = $this->db()->prepare($sql);
        foreach ($params as $key => $value) {
            $statement->bindValue($key, $value);
        }
        $statement->bindValue('limit', $limit, PDO::PARAM_INT);
        $statement->execute();

        return $statement->fetchAll();
    }

    public function approve(int $id): void
    {
        $statement = $this->db()->prepare('UPDATE artists SET status = "approved", verified = 1, rejection_reason = NULL, updated_at = NOW() WHERE id = :id');
        $statement->execute(['id' => $id]);
    }

    public function reject(int $id, string $reason): void
    {
        $statement = $this->db()->prepare('UPDATE artists SET status = "rejected", verified = 0, rejection_reason = :reason, updated_at = NOW() WHERE id = :id');
        $statement->execute(['id' => $id, 'reason' => trim($reason) ?: null]);
    }

    private function assertSlugAvailable(string $slug, ?int $exceptId = null): void
    {
        $sql = 'SELECT id FROM artists WHERE slug = :slug';
        $params = ['slug' => $slug];
        if ($exceptId !== null) {
            $sql .= ' AND id <> :id';
            $params['id'] = $exceptId;
        }
        $sql .= ' LIMIT 1';

        $statement = $this->db()->prepare($sql);
        $statement->execute($params);
        if ($statement->fetchColumn()) {
            throw new \InvalidArgumentException('Bu sanatci slug zaten kullaniliyor.');
        }
    }

    private function cleanUrl(string $value): ?string
    {
        $value = trim($value);
        if ($value === '') {
            return null;
        }

        if (filter_var($value, FILTER_VALIDATE_URL) === false) {
            throw new \InvalidArgumentException('Sosyal/platform linklerinden biri gecersiz.');
        }

        return substr($value, 0, 500);
    }

    private function slugify(string $value): string
    {
        $value = strtolower(trim($value));
        $value = strtr($value, [
            'ç' => 'c', 'ğ' => 'g', 'ı' => 'i', 'ö' => 'o', 'ş' => 's', 'ü' => 'u',
            'Ã§' => 'c', 'ÄŸ' => 'g', 'Ä±' => 'i', 'Ã¶' => 'o', 'ÅŸ' => 's', 'Ã¼' => 'u',
        ]);
        $value = preg_replace('/[^a-z0-9]+/', '-', $value) ?: '';

        return trim($value, '-');
    }
}
