<?php
declare(strict_types=1);

namespace App\Models;

use Core\DB;
use Core\Model;

final class User extends Model
{
    protected string $table = 'users';
    protected string $primaryKey = 'user_id';

    public static function findByLogin(int $tenantId, string $username): ?array
    {
        return DB::one(
            'SELECT u.*, r.code AS role_code, r.name AS role, t.name AS tenant_name
               FROM users u
          LEFT JOIN roles r   ON r.role_id   = u.role_id
          LEFT JOIN tenants t ON t.tenant_id = u.tenant_id
              WHERE u.tenant_id = :t
                AND u.username  = :u
                AND u.deleted_at IS NULL
                AND u.status = :st
              LIMIT 1',
            ['t' => $tenantId, 'u' => $username, 'st' => 'active']
        );
    }

    public static function verify(int $tenantId, string $username, string $password): ?array
    {
        $u = self::findByLogin($tenantId, $username);
        if (!$u || empty($u['password'])) return null;
        if (!password_verify($password, $u['password'])) return null;

        if (password_needs_rehash($u['password'], PASSWORD_DEFAULT)) {
            DB::run(
                'UPDATE users SET password = :p WHERE user_id = :id',
                ['p' => password_hash($password, PASSWORD_DEFAULT), 'id' => $u['user_id']]
            );
        }

        DB::run(
            'UPDATE users SET last_login_at = NOW() WHERE user_id = :id',
            ['id' => $u['user_id']]
        );
        return $u;
    }

    public static function listForTenant(int $tenantId): array
    {
        return DB::all(
            'SELECT u.user_id, u.username, u.f_name, u.l_name, u.email, u.phone, u.status,
                    u.last_login_at, r.code AS role_code, r.name AS role_name
               FROM users u
          LEFT JOIN roles r ON r.role_id = u.role_id
              WHERE u.tenant_id = :t AND u.deleted_at IS NULL
              ORDER BY u.username',
            ['t' => $tenantId]
        );
    }

    public static function findByIdInTenant(int $tenantId, int $userId): ?array
    {
        return DB::one(
            'SELECT * FROM users WHERE tenant_id = :t AND user_id = :id AND deleted_at IS NULL',
            ['t' => $tenantId, 'id' => $userId]
        );
    }

    public static function create(int $tenantId, array $data): int
    {
        $payload = [
            'tenant_id' => $tenantId,
            'role_id'   => $data['role_id']  ?? null,
            'username'  => $data['username'],
            'password'  => password_hash($data['password'], PASSWORD_DEFAULT),
            'f_name'    => $data['f_name']   ?? null,
            'l_name'    => $data['l_name']   ?? null,
            'email'     => $data['email']    ?? null,
            'phone'     => $data['phone']    ?? null,
            'job_title' => $data['job_title']?? null,
            'status'    => $data['status']   ?? 'active',
        ];
        return (int) DB::insert('users', $payload);
    }

    public static function update(int $tenantId, int $userId, array $data): void
    {
        $set = [];
        $params = ['t' => $tenantId, 'id' => $userId];
        foreach (['role_id','f_name','l_name','email','phone','job_title','status'] as $col) {
            if (array_key_exists($col, $data)) {
                $set[] = "`{$col}` = :{$col}";
                $params[$col] = $data[$col];
            }
        }
        if (!empty($data['password'])) {
            $set[] = '`password` = :password';
            $params['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
        }
        if (!$set) return;
        DB::run(
            'UPDATE users SET ' . implode(', ', $set) . ' WHERE tenant_id = :t AND user_id = :id',
            $params
        );
    }

    public static function softDelete(int $tenantId, int $userId): void
    {
        DB::run(
            'UPDATE users SET deleted_at = NOW(), status = "inactive" WHERE tenant_id = :t AND user_id = :id',
            ['t' => $tenantId, 'id' => $userId]
        );
    }
}
