<?php

declare(strict_types=1);

namespace backend\controllers;

use common\models\FoodLibrary;
use yii\data\ActiveDataProvider;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\web\Response;
use yii\web\UploadedFile;

/**
 * FoodLibraryController — manage global and user-specific food items.
 * Also handles CSV import via batchInsert.
 */
class FoodLibraryController extends Controller
{
    public function behaviors(): array
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [['allow' => true, 'roles' => ['@']]],
            ],
            'verbs' => [
                'class'   => VerbFilter::class,
                'actions' => ['delete' => ['POST']],
            ],
        ];
    }

    public function actionIndex(): string
    {
        $userId = (int)\Yii::$app->user->id;

        $query = FoodLibrary::find()
            ->where(['OR', ['user_id' => null], ['user_id' => $userId]])
            ->orderBy(['name' => SORT_ASC]);

        $category = \Yii::$app->request->get('category');
        if ($category) {
            $query->andWhere(['category' => $category]);
        }

        $search = \Yii::$app->request->get('search');
        if ($search) {
            $query->andWhere(['LIKE', 'name', $search]);
        }

        $dataProvider = new ActiveDataProvider([
            'query'      => $query,
            'pagination' => ['pageSize' => 30],
        ]);

        return $this->render('index', [
            'dataProvider' => $dataProvider,
            'filterCategory' => $category,
            'search'       => $search,
        ]);
    }

    public function actionCreate(): Response|string
    {
        $model = new FoodLibrary();
        $model->user_id = (int)\Yii::$app->user->id;

        if ($model->load(\Yii::$app->request->post()) && $model->save()) {
            \Yii::$app->session->setFlash('success', 'Food item added.');
            return $this->redirect(['index']);
        }

        return $this->render('create', ['model' => $model]);
    }

    public function actionUpdate(int $id): Response|string
    {
        $model = $this->findModel($id);

        if ($model->load(\Yii::$app->request->post()) && $model->save()) {
            \Yii::$app->session->setFlash('success', 'Food item updated.');
            return $this->redirect(['index']);
        }

        return $this->render('update', ['model' => $model]);
    }

    public function actionDelete(int $id): Response
    {
        $this->findModel($id)->delete();
        // Invalidate food cache
        \Yii::$app->cache->delete('food_library_all');
        \Yii::$app->session->setFlash('success', 'Food item deleted.');
        return $this->redirect(['index']);
    }

    /**
     * CSV Import — batch insert with field mapping.
     * Expected CSV columns: name,category,calories,protein,carbs,fats,fiber
     */
    public function actionImport(): Response|string
    {
        if (\Yii::$app->request->isPost) {
            $file = UploadedFile::getInstanceByName('csv_file');

            if ($file === null) {
                \Yii::$app->session->setFlash('error', 'No CSV file uploaded.');
                return $this->render('import');
            }

            $rows    = [];
            $errors  = [];
            $lineNum = 0;
            $handle  = fopen($file->tempName, 'r');
            $headers = null;

            while (($line = fgetcsv($handle)) !== false) {
                $lineNum++;
                if ($lineNum === 1) {
                    // Normalize headers
                    $headers = array_map('strtolower', array_map('trim', $line));
                    continue;
                }

                if (empty(array_filter($line))) {
                    continue;
                }

                $row = array_combine($headers, $line);

                if (empty($row['name'])) {
                    $errors[] = "Line {$lineNum}: name is required.";
                    continue;
                }

                $ts = time();
                $rows[] = [
                    'user_id'      => null, // imported as global
                    'name'         => trim($row['name']),
                    'category'     => trim($row['category'] ?? ''),
                    'calories'     => (float)($row['calories'] ?? 0),
                    'protein'      => (float)($row['protein'] ?? 0),
                    'carbs'        => (float)($row['carbs'] ?? 0),
                    'fats'         => (float)($row['fats'] ?? 0),
                    'fiber'        => (float)($row['fiber'] ?? 0),
                    'is_active'    => 1,
                    'created_at'   => $ts,
                    'updated_at'   => $ts,
                ];
            }
            fclose($handle);

            if (!empty($rows)) {
                \Yii::$app->db->createCommand()->batchInsert(
                    '{{%food_library}}',
                    ['user_id', 'name', 'category', 'calories', 'protein', 'carbs', 'fats', 'fiber', 'is_active', 'created_at', 'updated_at'],
                    array_values(array_map(fn($r) => array_values($r), $rows))
                )->execute();
            }

            $msg = count($rows) . ' foods imported.';
            if ($errors) {
                $msg .= ' ' . count($errors) . ' rows skipped.';
            }
            \Yii::$app->session->setFlash('success', $msg);
            return $this->redirect(['index']);
        }

        return $this->render('import');
    }

    private function findModel(int $id): FoodLibrary
    {
        $model = FoodLibrary::findOne($id);
        if ($model === null) {
            throw new NotFoundHttpException('Food item not found.');
        }
        return $model;
    }
}
