<?php
namespace app\models;

use app\app;

class products
{
    public static function init()
    {
        // max 12 images and 12 specification key/value pairs allowed
        $imageColumns = '';
        $specColumns  = '';
        for ($i = 0; $i < 12; $i++) {
            $imageColumns .= "image_url_$i TEXT" . ($i === 0 ? " NOT NULL" : "") . ", ";
            $specColumns .= "spec_key_$i TEXT, spec_val_$i TEXT, ";
        }
        $imageColumns = rtrim($imageColumns, ', ');
        $specColumns  = rtrim($specColumns, ', ');

        app::$db->exec("CREATE TABLE IF NOT EXISTS products (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            category_id INTEGER REFERENCES categories(id),
            title TEXT NOT NULL,
            description TEXT,
            stock_qty INTEGER,
            is_unlimited BOOLEAN,
            is_enabled BOOLEAN,
            is_quote_only BOOLEAN,
            price_sats INTEGER,
            sats_back_percent INTEGER,
            is_accepting_sats BOOLEAN,
            is_sats_back_only BOOLEAN,
            price_cents INTEGER,
            cents_back_percent INTEGER,
            is_accepting_cents BOOLEAN,
            is_cents_back_only BOOLEAN,
            is_digital BOOLEAN,
            oz REAL,
            lbs REAL,
            length REAL,
            width REAL,
            height REAL,
            is_subscription BOOLEAN,
            is_subscription_only BOOLEAN,
            subscription_frequency TEXT,
            $imageColumns,
            $specColumns
        )");
    }

    public static function validateProductData($data)
    {
        $error_messages         = [];
        $title                  = $data['title'] ?? null;
        $description            = $data['description'] ?? null;
        $price_sats             = $data['price_sats'] ?? null;
        $price_cents            = $data['price_cents'] ?? null;
        $stock_qty              = $data['stock_qty'] ?? null;
        $is_digital             = $data['is_digital'] ?? false;
        $is_subscription        = $data['is_subscription'] ?? false;
        $is_subscription_only   = $data['is_subscription_only'] ?? false;
        $is_quote_only          = $data['is_quote_only'] ?? false;
        $oz                     = $data['oz'] ?? null;
        $lbs                    = $data['lbs'] ?? null;
        $length                 = $data['length'] ?? null;
        $width                  = $data['width'] ?? null;
        $height                 = $data['height'] ?? null;
        $category_id            = $data['category_id'] ?? null;
        $is_unlimited           = $data['is_unlimited'] ?? false;
        $is_sats_back_only      = $data['is_sats_back_only'] ?? false;
        $is_cents_back_only     = $data['is_cents_back_only'] ?? false;
        $is_enabled             = $data['is_enabled'] ?? false;
        $is_accepting_sats      = $data['is_accepting_sats'] ?? false;
        $is_accepting_cents     = $data['is_accepting_cents'] ?? false;
        $subscription_frequency = $data['subscription_frequency'] ?? null;
        $images                 = [];
        for ($i = 0; $i <= 11; $i++) {
            $images[] = $data['image_url_' . $i] ?? null;
        }
        $specs = [];
        for ($i = 0; $i <= 11; $i++) {
            $key = $_POST['spec_key_' . $i] ?? null;
            $val = $_POST['spec_val_' . $i] ?? null;
            if ($key !== null || $val !== null) {
                if ($key === null || $val === null) {
                    $error_messages[] = 'Each specification key must have a corresponding value.';
                }
                $specs[] = ['key' => $key, 'value' => $val];
            }
        }

        if (! $title) {
            $error_messages[] = 'Title is a required field.';
        }
        if (! $description) {
            $error_messages[] = 'Description is a required field.';
        }
        if (! $category_id) {
            $error_messages[] = 'Category is a required field.';
        }
        if (! $images[0]) {
            $error_messages[] = 'The first image URL is a required field.';
        }
        if (! $is_unlimited && ! $stock_qty) {
            $error_messages[] = 'Quantity is required unless the product is marked as unlimited.';
        }

        if (! $is_quote_only) {
            if ($price_sats === null && $price_cents === null) {
                $error_messages[] = 'Either price in sats or price in cents must be set. They can be zero.';
            }
            if ($is_cents_back_only && $is_sats_back_only) {
                $error_messages[] = 'A product cannot be both cents back only and sats back only.';
            }
        }

        if (! $is_digital) {
            if ($oz === null || $lbs === null || $length === null || $width === null || $height === null) {
                $error_messages[] = 'For non-digital products, weight (oz and lbs), length, width, and height are required fields.';
            }
        }
        if ($is_subscription_only && ! $is_subscription) {
            $error_messages[] = 'If the product is subscription only, it must also enable subscriptions.';
        }

        return [
            'errors'                 => $error_messages,
            'title'                  => $title,
            'description'            => $description,
            'category_id'            => $category_id,
            'images'                 => $images,
            'specs'                  => $specs,
            'stock_qty'              => $stock_qty,
            'price_sats'             => $price_sats,
            'price_cents'            => $price_cents,
            'is_digital'             => $is_digital,
            'is_subscription'        => $is_subscription,
            'is_subscription_only'   => $is_subscription_only,
            'is_enabled'             => $is_enabled,
            'is_unlimited'           => $is_unlimited,
            'is_accepting_sats'      => $is_accepting_sats,
            'is_accepting_cents'     => $is_accepting_cents,
            'is_sats_back_only'      => $is_sats_back_only,
            'is_cents_back_only'     => $is_cents_back_only,
            'subscription_frequency' => $subscription_frequency,
            'is_quote_only'          => $is_quote_only,
            'oz'                     => $oz,
            'lbs'                    => $lbs,
            'length'                 => $length,
            'width'                  => $width,
            'height'                 => $height,
        ];
    }

    public static function add($productData)
    {
        $imageColumns = '';
        $imageValues  = '';
        $specColumns  = '';
        $specValues   = '';

        for ($i = 0; $i < 12; $i++) {
            $imageColumns .= "image_url_$i, ";
            $imageValues .= ":image_url_$i, ";
            $specColumns .= "spec_key_$i, spec_val_$i, ";
            $specValues .= ":spec_key_$i, :spec_val_$i, ";
        }

        $imageColumns = rtrim($imageColumns, ', ');
        $imageValues  = rtrim($imageValues, ', ');
        $specColumns  = rtrim($specColumns, ', ');
        $specValues   = rtrim($specValues, ', ');

        $stmt = app::$db->prepare("INSERT INTO products (
            title, description, stock_qty, price_sats, price_cents, is_digital, is_subscription, is_subscription_only, is_enabled, is_unlimited, is_accepting_sats, is_accepting_cents, is_sats_back_only, is_cents_back_only, subscription_frequency, is_quote_only, category_id, oz, lbs, length, width, height,
            $imageColumns, $specColumns
        ) VALUES (
            :title, :description, :stock_qty, :price_sats, :price_cents, :is_digital, :is_subscription, :is_subscription_only, :is_enabled, :is_unlimited, :is_accepting_sats, :is_accepting_cents, :is_sats_back_only, :is_cents_back_only, :subscription_frequency, :is_quote_only, :category_id, :oz, :lbs, :length, :width, :height,
            $imageValues, $specValues
        )");

        $stmt->bindValue(':title', $productData['title']);
        $stmt->bindValue(':description', $productData['description']);
        $stmt->bindValue(':stock_qty', $productData['stock_qty']);
        $stmt->bindValue(':price_sats', $productData['price_sats']);
        $stmt->bindValue(':price_cents', $productData['price_cents']);
        $stmt->bindValue(':is_digital', (bool) $productData['is_digital'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_subscription', (bool) $productData['is_subscription'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_subscription_only', (bool) $productData['is_subscription_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_enabled', (bool) $productData['is_enabled'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_unlimited', (bool) $productData['is_unlimited'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_accepting_sats', (bool) $productData['is_accepting_sats'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_accepting_cents', (bool) $productData['is_accepting_cents'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_sats_back_only', (bool) $productData['is_sats_back_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_cents_back_only', (bool) $productData['is_cents_back_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':subscription_frequency', $productData['subscription_frequency']);
        $stmt->bindValue(':is_quote_only', (bool) $productData['is_quote_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':category_id', $productData['category_id'], \PDO::PARAM_INT);
        $stmt->bindValue(':oz', $productData['oz']);
        $stmt->bindValue(':lbs', $productData['lbs']);
        $stmt->bindValue(':length', $productData['length']);
        $stmt->bindValue(':width', $productData['width']);
        $stmt->bindValue(':height', $productData['height']);

        for ($i = 0; $i < 12; $i++) {
            $stmt->bindValue(":image_url_$i", $productData['images'][$i] ?? null);
            $stmt->bindValue(":spec_key_$i", $productData['specs'][$i]['key'] ?? null);
            $stmt->bindValue(":spec_val_$i", $productData['specs'][$i]['value'] ?? null);
        }

        $stmt->execute();
    }

    public static function update($id, $productData)
    {
        $imageColumns = '';
        $specColumns  = '';

        for ($i = 0; $i < 12; $i++) {
            $imageColumns .= "image_url_$i = :image_url_$i, ";
            $specColumns .= "spec_key_$i = :spec_key_$i, spec_val_$i = :spec_val_$i, ";
        }

        $imageColumns = rtrim($imageColumns, ', ');
        $specColumns  = rtrim($specColumns, ', ');

        $stmt = app::$db->prepare("UPDATE products SET
            title = :title,
            description = :description,
            stock_qty = :stock_qty,
            price_sats = :price_sats,
            price_cents = :price_cents,
            is_digital = :is_digital,
            is_subscription = :is_subscription,
            is_subscription_only = :is_subscription_only,
            is_enabled = :is_enabled,
            is_unlimited = :is_unlimited,
            is_accepting_sats = :is_accepting_sats,
            is_accepting_cents = :is_accepting_cents,
            is_sats_back_only = :is_sats_back_only,
            is_cents_back_only = :is_cents_back_only,
            subscription_frequency = :subscription_frequency,
            is_quote_only = :is_quote_only,
            category_id = :category_id,
            oz = :oz,
            lbs = :lbs,
            length = :length,
            width = :width,
            height = :height,
            $imageColumns,
            $specColumns
            WHERE id = :id");

        $stmt->bindValue(':id', (int) $id, \PDO::PARAM_INT);
        $stmt->bindValue(':title', $productData['title']);
        $stmt->bindValue(':description', $productData['description']);
        $stmt->bindValue(':stock_qty', $productData['stock_qty']);
        $stmt->bindValue(':price_sats', $productData['price_sats']);
        $stmt->bindValue(':price_cents', $productData['price_cents']);
        $stmt->bindValue(':is_digital', (bool) $productData['is_digital'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_subscription', (bool) $productData['is_subscription'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_subscription_only', (bool) $productData['is_subscription_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_enabled', (bool) $productData['is_enabled'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_unlimited', (bool) $productData['is_unlimited'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_accepting_sats', (bool) $productData['is_accepting_sats'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_accepting_cents', (bool) $productData['is_accepting_cents'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_sats_back_only', (bool) $productData['is_sats_back_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':is_cents_back_only', (bool) $productData['is_cents_back_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':subscription_frequency', $productData['subscription_frequency']);
        $stmt->bindValue(':is_quote_only', (bool) $productData['is_quote_only'], \PDO::PARAM_BOOL);
        $stmt->bindValue(':category_id', $productData['category_id'], \PDO::PARAM_INT);
        $stmt->bindValue(':oz', $productData['oz']);
        $stmt->bindValue(':lbs', $productData['lbs']);
        $stmt->bindValue(':length', $productData['length']);
        $stmt->bindValue(':width', $productData['width']);
        $stmt->bindValue(':height', $productData['height']);

        for ($i = 0; $i < 12; $i++) {
            $stmt->bindValue(":image_url_$i", $productData['images'][$i] ?? null);
            $stmt->bindValue(":spec_key_$i", $productData['specs'][$i]['key'] ?? null);
            $stmt->bindValue(":spec_val_$i", $productData['specs'][$i]['value'] ?? null);
        }

        $stmt->execute();
    }

    public static function get($limit)
    {
        $stmt = app::$db->prepare("SELECT * FROM products LIMIT :limit");
        $stmt->bindValue(':limit', (int) $limit, \PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
    }
    public static function getById($id)
    {
        $stmt = app::$db->prepare("SELECT * FROM products WHERE id = :id");
        $stmt->bindValue(':id', (int) $id, \PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetch(\PDO::FETCH_ASSOC);
    }
}
