<?php

namespace app\controllers;

use Yii;
use app\models\Client;
use app\models\User;
use app\models\Car;
use yii\web\NotFoundHttpException;
use yii\web\ForbiddenHttpException;
use yii\filters\VerbFilter;

class ClientController extends BaseController
{
    public function behaviors(): array
    {
        return array_merge(parent::behaviors(), [
            'verbs' => [
                'class' => VerbFilter::class,
                'actions' => [
                    'delete'          => ['POST'],
                    'change-password' => ['POST'],
                ],
            ],
        ]);
    }

    // ── ADMIN: List all clients ────────────────────────────────────
    public function actionIndex()
    {
        $rows = Client::find()->orderBy(['no' => SORT_DESC])->asArray()->all();
        return $this->render('index', ['rows' => $rows]);
    }

    // ── CLIENT: Dashboard ──────────────────────────────────────────
    public function actionDashboard()
    {
        $clientId = (int) Yii::$app->user->identity->client_id;

        $statusRows = Yii::$app->db->createCommand('
            SELECT status, COUNT(*) as cnt
            FROM car WHERE client_id = :cid GROUP BY status
        ')->bindValue(':cid', $clientId)->queryAll();

        $statusCounts = [];
        foreach ($statusRows as $row) {
            $statusCounts[$row['status']] = (int) $row['cnt'];
        }

        $recentCars = Car::find()
            ->with(['auction', 'warehouse', 'destination', 'images'])
            ->where(['client_id' => $clientId])
            ->orderBy(['id' => SORT_DESC])
            ->limit(5)
            ->all();

        return $this->render('dashboard', [
            'statusCounts' => $statusCounts,
            'totalCars'    => array_sum($statusCounts),
            'recentCars'   => $recentCars,
            'client'       => Client::findOne($clientId),
            'uploadUrl'    => Yii::$app->request->baseUrl . '/uploads/cars/',
        ]);
    }

    // ── CLIENT: My Cars ────────────────────────────────────────────
    public function actionMyCars()
    {
        $clientId  = (int) Yii::$app->user->identity->client_id;
        $uploadUrl = Yii::$app->request->baseUrl . '/uploads/cars/';

        if (Yii::$app->request->isAjax || Yii::$app->request->get('ajax')) {
            $page     = (int) Yii::$app->request->get('page', 1);
            $pageSize = (int) Yii::$app->request->get('pageSize', 15);
            $search   = trim(Yii::$app->request->get('search', ''));

            $query = Car::find()
                ->with(['auction', 'warehouse', 'destination'])
                ->where(['client_id' => $clientId])
                ->orderBy(['id' => SORT_DESC]);

            if ($search !== '') {
                $query->andWhere(['or',
                    ['like', 'vin',       $search],
                    ['like', 'lot',       $search],
                    ['like', 'info',      $search],
                    ['like', 'container', $search],
                    ['like', 'year',      $search],
                    ['like', 'status',    $search],
                ]);
            }

            $totalCount   = (clone $query)->count();
            $cars         = $query->offset(($page - 1) * $pageSize)->limit($pageSize)->all();
            $thumbnailMap = $this->batchThumbnails(array_map(fn($c) => $c->id, $cars));

            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
            return [
                'success'    => true,
                'cars'       => $this->formatCars($cars, $thumbnailMap),
                'total'      => (int) $totalCount,
                'page'       => $page,
                'pageSize'   => $pageSize,
                'totalPages' => (int) ceil($totalCount / $pageSize),
            ];
        }

        $pageSize   = 15;
        $totalCount = Car::find()->where(['client_id' => $clientId])->count();
        $firstPage  = Car::find()
            ->with(['auction', 'warehouse', 'destination'])
            ->where(['client_id' => $clientId])
            ->orderBy(['id' => SORT_DESC])
            ->limit($pageSize)->all();

        $statusRows = Yii::$app->db->createCommand('
            SELECT status, COUNT(*) as cnt FROM car WHERE client_id = :cid GROUP BY status
        ')->bindValue(':cid', $clientId)->queryAll();

        $statusCounts = [];
        foreach ($statusRows as $row) {
            $statusCounts[$row['status']] = (int) $row['cnt'];
        }

        $thumbnailMap = $this->batchThumbnails(array_map(fn($c) => $c->id, $firstPage));

        return $this->render('my-cars', [
            'cars'         => $this->formatCars($firstPage, $thumbnailMap),
            'totalCount'   => (int) $totalCount,
            'statusCounts' => $statusCounts,
            'uploadUrl'    => $uploadUrl,
        ]);
    }

    // ── CLIENT: View single car ────────────────────────────────────
    public function actionViewCar($id)
    {
        $clientId = (int) Yii::$app->user->identity->client_id;

        $car = Car::find()
            ->with(['images', 'auction', 'warehouse', 'destination'])
            ->where(['id' => (int) $id, 'client_id' => $clientId])
            ->one();

        if (!$car) {
            throw new ForbiddenHttpException('Car not found or access denied.');
        }

        return $this->render('view-car', [
            'car'       => $car,
            'uploadUrl' => Yii::$app->request->baseUrl . '/uploads/cars/',
        ]);
    }

    // ── CLIENT: Profile ────────────────────────────────────────────
    public function actionProfile()
    {
        $identity = Yii::$app->user->identity;
        $user     = User::findOne((int) $identity->id);
        $client   = Client::findOne((int) $identity->client_id);

        if (!$user || !$client) {
            throw new ForbiddenHttpException('Profile not found.');
        }

        return $this->render('profile', ['user' => $user, 'client' => $client]);
    }

    // ── CLIENT: Change Password ────────────────────────────────────
    public function actionChangePassword()
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $user = User::findOne((int) Yii::$app->user->identity->id);
        if (!$user) return ['success' => false, 'message' => 'User not found.'];

        $current = Yii::$app->request->post('current_password', '');
        $new     = Yii::$app->request->post('new_password', '');
        $confirm = Yii::$app->request->post('confirm_password', '');

        if (empty($current) || empty($new) || empty($confirm))
            return ['success' => false, 'message' => 'All password fields are required.'];

        if (!Yii::$app->security->validatePassword($current, $user->password))
            return ['success' => false, 'message' => 'Current password is incorrect.'];

        if (strlen($new) < 6)
            return ['success' => false, 'message' => 'New password must be at least 6 characters.'];

        if ($new !== $confirm)
            return ['success' => false, 'message' => 'New passwords do not match.'];

        $user->password = Yii::$app->security->generatePasswordHash($new);
        $user->auth_key = Yii::$app->security->generateRandomString();

        return $user->save(false)
            ? ['success' => true,  'message' => 'Password changed successfully!']
            : ['success' => false, 'message' => 'Failed to save. Please try again.'];
    }

    // ── ADMIN: Save client ─────────────────────────────────────────
    public function actionSaveAjax()
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $data  = json_decode(Yii::$app->request->getRawBody(), true);
        if (empty($data)) $data = Yii::$app->request->post();

        $isNew = empty($data['id']);
        $model = !$isNew ? Client::findOne($data['id']) : new Client();

        $model->name     = $data['name']     ?? null;
        $model->phone    = $data['phone']    ?? null;
        $model->email    = $data['email']    ?? null;
        $model->address  = $data['address']  ?? null;
        $model->town     = $data['town']     ?? null;
        $model->country  = $data['country']  ?? null;
        $model->balance  = $data['balance']  ?? 0;
        $model->username = $data['username'] ?? null;
        $model->password = $data['password'] ?? null;

        $transaction = Yii::$app->db->beginTransaction();
        try {
            if (!empty($model->username)) {
                $q = User::find()->where(['username' => $model->username]);
                if (!$isNew) $q->andWhere(['!=', 'client_id', $model->id]);
                if ($q->exists()) throw new \Exception("Username '{$model->username}' is already taken.");
            }

            if ($isNew) {
                $maxNo     = Client::find()->max('CAST(no AS UNSIGNED)');
                $model->no = str_pad(($maxNo ? (int)$maxNo + 1 : 1), 5, '0', STR_PAD_LEFT);
            }

            if (!$model->save())
                throw new \Exception("Client Error: " . implode(", ", $model->getFirstErrors()));

            $user = !$isNew ? User::findOne(['client_id' => $model->id]) : new User();
            if (!$user) $user = new User();

            $user->client_id  = $model->id;
            $user->auction_id = $user->auction_id ?? 0;
            $user->name       = $model->name;
            $user->email      = $model->email;
            $user->phone      = $model->phone;
            $user->username   = $model->username;
            $user->position   = 'client';

            if (!empty($model->password)) {
                $user->password = Yii::$app->security->generatePasswordHash($model->password);
                $user->auth_key = Yii::$app->security->generateRandomString();
            } elseif ($isNew) {
                throw new \Exception("Password is required for new clients.");
            }

            if (!$user->save())
                throw new \Exception("User Account Error: " . implode(", ", $user->getFirstErrors()));

            $transaction->commit();
            return ['success' => true, 'client' => $model->attributes];

        } catch (\Exception $e) {
            $transaction->rollBack();
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    // ── ADMIN: Delete client ───────────────────────────────────────
    public function actionDelete($id)
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $transaction = Yii::$app->db->beginTransaction();
        try {
            $client = Client::findOne($id);
            if (!$client) return ['success' => false, 'message' => 'Client not found.'];

            if (Car::find()->where(['client_id' => $id])->exists())
                return ['success' => false, 'message' => 'Cannot delete: Client has car records.'];

            User::deleteAll(['email' => $client->email]);

            if (!$client->delete()) throw new \Exception("Failed to delete client.");

            $transaction->commit();
            return ['success' => true];

        } catch (\Exception $e) {
            $transaction->rollBack();
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    // ── ADMIN: Get next client no ──────────────────────────────────
    public function actionGetNextNo()
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $maxNo = Client::find()->max('CAST(no AS UNSIGNED)');
        return ['next_no' => str_pad(($maxNo ? (int)$maxNo + 1 : 1), 5, '0', STR_PAD_LEFT)];
    }

    // ── Helpers ────────────────────────────────────────────────────
    protected function findModel($id)
    {
        if (($model = Client::findOne(['id' => $id])) !== null) return $model;
        throw new NotFoundHttpException('The requested page does not exist.');
    }

    private function batchThumbnails(array $carIds): array
    {
        if (empty($carIds)) return [];
        $rows = Yii::$app->db->createCommand('
            SELECT ci.car_id, ci.image_path
            FROM car_image ci
            INNER JOIN (
                SELECT MIN(id) AS min_id FROM car_image
                WHERE car_id IN (' . implode(',', $carIds) . ')
                GROUP BY car_id
            ) first ON ci.id = first.min_id
        ')->queryAll();
        $map = [];
        foreach ($rows as $row) $map[$row['car_id']] = $row['image_path'];
        return $map;
    }

    private function formatCars(array $cars, array $thumbnailMap = []): array
    {
        $data = [];
        foreach ($cars as $car) {
            $data[] = [
                'id'               => $car->id,
                'vin'              => $car->vin,
                'lot'              => $car->lot,
                'title'            => $car->title,
                'info'             => $car->info,
                'liner'            => $car->liner,
                'year'             => $car->year,
                'price'            => $car->price,
                'status'           => $car->status,
                'note'             => $car->note,
                'purchase_date'    => $car->purchase_date,
                'received_date'    => $car->received_date,
                'eta_date'         => $car->eta_date,
                'shipping_line'    => $car->shipping_line,
                'container'        => $car->container,
                'auction_name'     => $car->auction     ? $car->auction->name     : '',
                'warehouse_name'   => $car->warehouse   ? $car->warehouse->name   : '',
                'destination_name' => $car->destination ? $car->destination->name : '',
                'thumbnail'        => $thumbnailMap[$car->id] ?? null,
                'images'           => [],
            ];
        }
        return $data;
    }
}
