<?php
declare(strict_types=1);

namespace App\Models;

class CreatorLedger extends BaseModel
{
    protected string $table = 'creator_ledgers';

    public const TYPES = [
        'sale_income',
        'commission_deducted',
        'tax_deducted',
        'provider_fee_deducted',
        'withdrawal_requested',
        'withdrawal_approved',
        'withdrawal_sent',
        'withdrawal_rejected',
        'refund_deducted',
        'manual_adjustment',
    ];

    public function createEntry(array $data): array
    {
        $type = in_array((string) ($data['type'] ?? ''), self::TYPES, true)
            ? (string) $data['type']
            : 'manual_adjustment';
        $userId = (int) ($data['user_id'] ?? $data['creator_id'] ?? 0);

        $statement = $this->db()->prepare(
            'INSERT INTO creator_ledgers
                (creator_id, user_id, order_id, withdrawal_id, type, amount, balance_before, balance_after,
                 currency, description, available_at, created_at)
             VALUES
                (:creator_id, :user_id, :order_id, :withdrawal_id, :type, :amount, :balance_before, :balance_after,
                 :currency, :description, :available_at, NOW())'
        );
        $statement->execute([
            'creator_id' => $userId,
            'user_id' => $userId,
            'order_id' => $data['order_id'] ?? null,
            'withdrawal_id' => $data['withdrawal_id'] ?? null,
            'type' => $type,
            'amount' => round((float) ($data['amount'] ?? 0), 2),
            'balance_before' => round((float) ($data['balance_before'] ?? 0), 2),
            'balance_after' => round((float) ($data['balance_after'] ?? 0), 2),
            'currency' => strtoupper(substr((string) ($data['currency'] ?? 'TRY'), 0, 3)),
            'description' => $data['description'] ?? null,
            'available_at' => $data['available_at'] ?? null,
        ]);

        return $this->find((int) $this->db()->lastInsertId()) ?? [];
    }

    public function existsForOrderType(int $userId, int $orderId, string $type): bool
    {
        $statement = $this->db()->prepare(
            'SELECT id FROM creator_ledgers
             WHERE (user_id = :user_id OR creator_id = :creator_id)
               AND order_id = :order_id
               AND type = :type
             LIMIT 1'
        );
        $statement->execute([
            'user_id' => $userId,
            'creator_id' => $userId,
            'order_id' => $orderId,
            'type' => $type,
        ]);

        return (bool) $statement->fetchColumn();
    }

    public function recentForUser(int $userId, int $limit = 50): array
    {
        $statement = $this->db()->prepare(
            'SELECT cl.*, o.order_no
             FROM creator_ledgers cl
             LEFT JOIN orders o ON o.id = cl.order_id
             WHERE cl.user_id = :user_id OR cl.creator_id = :creator_id
             ORDER BY cl.id DESC
             LIMIT :limit'
        );
        $statement->bindValue('user_id', $userId, \PDO::PARAM_INT);
        $statement->bindValue('creator_id', $userId, \PDO::PARAM_INT);
        $statement->bindValue('limit', max(1, min(200, $limit)), \PDO::PARAM_INT);
        $statement->execute();

        return $statement->fetchAll();
    }

    public function recentForAdmin(int $limit = 100): array
    {
        $statement = $this->db()->prepare(
            'SELECT cl.*, o.order_no, u.username, COALESCE(up.display_name, p.display_name, u.nickname, u.username) AS creator_name
             FROM creator_ledgers cl
             LEFT JOIN orders o ON o.id = cl.order_id
             LEFT JOIN users u ON u.id = COALESCE(cl.user_id, cl.creator_id)
             LEFT JOIN user_profiles up ON up.user_id = u.id
             LEFT JOIN profiles p ON p.user_id = u.id
             ORDER BY cl.id DESC
             LIMIT :limit'
        );
        $statement->bindValue('limit', max(1, min(300, $limit)), \PDO::PARAM_INT);
        $statement->execute();

        return $statement->fetchAll();
    }
}
