<?php

class DiscountPolicy {
    private $conn;

    public function __construct($conn) {
        $this->conn = $conn;
        $this->ensureTables();
    }

    private function ensureTables() {
        $this->conn->exec("
            CREATE TABLE IF NOT EXISTS discount_rules (
                rule_id INT AUTO_INCREMENT PRIMARY KEY,
                rule_name VARCHAR(120) NOT NULL,
                discount_type ENUM('percentage','fixed') NOT NULL,
                discount_value DECIMAL(15,2) NOT NULL,
                max_sale_amount DECIMAL(15,2) DEFAULT NULL,
                is_active TINYINT(1) NOT NULL DEFAULT 1,
                created_by INT DEFAULT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_discount_rules_active (is_active, discount_type, discount_value)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
        ");

        $this->conn->exec("
            CREATE TABLE IF NOT EXISTS discount_approval_requests (
                request_id INT AUTO_INCREMENT PRIMARY KEY,
                branch_id INT NOT NULL,
                requested_by INT NOT NULL,
                discount_type ENUM('percentage','fixed') NOT NULL,
                discount_value DECIMAL(15,2) NOT NULL,
                sale_total DECIMAL(15,2) NOT NULL DEFAULT 0,
                reason TEXT DEFAULT NULL,
                status ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending',
                reviewed_by INT DEFAULT NULL,
                reviewed_at DATETIME DEFAULT NULL,
                review_notes TEXT DEFAULT NULL,
                created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_discount_requests_status (status),
                INDEX idx_discount_requests_branch (branch_id)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
        ");
    }

    public function getActiveRules() {
        $stmt = $this->conn->query("SELECT * FROM discount_rules WHERE is_active = 1 ORDER BY discount_type, discount_value");
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function isDiscountAllowed($type, $value, $saleTotal) {
        $type = strtolower(trim((string)$type));
        $value = round((float)$value, 2);
        if ($type === 'none' || $value <= 0) {
            return true;
        }
        if (!in_array($type, ['percentage', 'fixed'], true)) {
            return false;
        }

        $stmt = $this->conn->prepare("
            SELECT COUNT(*)
            FROM discount_rules
            WHERE is_active = 1
              AND discount_type = :discount_type
              AND ABS(discount_value - :discount_value) < 0.01
              AND (max_sale_amount IS NULL OR max_sale_amount = 0 OR :sale_total <= max_sale_amount)
        ");
        $stmt->execute([
            ':discount_type' => $type,
            ':discount_value' => $value,
            ':sale_total' => round((float)$saleTotal, 2),
        ]);
        return (int)$stmt->fetchColumn() > 0;
    }

    public function requestApproval($branchId, $requestedBy, $type, $value, $saleTotal, $reason = '') {
        $stmt = $this->conn->prepare("
            INSERT INTO discount_approval_requests
                (branch_id, requested_by, discount_type, discount_value, sale_total, reason)
            VALUES
                (:branch_id, :requested_by, :discount_type, :discount_value, :sale_total, :reason)
        ");
        $stmt->execute([
            ':branch_id' => (int)$branchId,
            ':requested_by' => (int)$requestedBy,
            ':discount_type' => strtolower(trim((string)$type)),
            ':discount_value' => round((float)$value, 2),
            ':sale_total' => round((float)$saleTotal, 2),
            ':reason' => trim((string)$reason),
        ]);
        return (int)$this->conn->lastInsertId();
    }

    public function getRequests($status = '') {
        $sql = "SELECT r.*, b.branch_name, u.username AS requested_by_name, reviewer.username AS reviewed_by_name
                FROM discount_approval_requests r
                LEFT JOIN branches b ON b.branch_id = r.branch_id
                LEFT JOIN users u ON u.user_id = r.requested_by
                LEFT JOIN users reviewer ON reviewer.user_id = r.reviewed_by";
        $params = [];
        if ($status !== '') {
            $sql .= " WHERE r.status = :status";
            $params[':status'] = $status;
        }
        $sql .= " ORDER BY r.created_at DESC";
        $stmt = $this->conn->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function reviewRequest($requestId, $status, $reviewedBy, $notes = '', $createRule = false) {
        if (!in_array($status, ['approved', 'rejected'], true)) {
            throw new InvalidArgumentException('Invalid discount review status.');
        }

        $stmt = $this->conn->prepare("SELECT * FROM discount_approval_requests WHERE request_id = :request_id LIMIT 1");
        $stmt->execute([':request_id' => (int)$requestId]);
        $request = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$request || $request['status'] !== 'pending') {
            throw new RuntimeException('Discount request was not found or is already reviewed.');
        }

        $this->conn->beginTransaction();
        try {
            $update = $this->conn->prepare("
                UPDATE discount_approval_requests
                SET status = :status, reviewed_by = :reviewed_by, reviewed_at = NOW(), review_notes = :notes
                WHERE request_id = :request_id
            ");
            $update->execute([
                ':status' => $status,
                ':reviewed_by' => (int)$reviewedBy,
                ':notes' => trim((string)$notes),
                ':request_id' => (int)$requestId,
            ]);

            if ($status === 'approved' && $createRule) {
                $rule = $this->conn->prepare("
                    INSERT INTO discount_rules (rule_name, discount_type, discount_value, max_sale_amount, created_by)
                    VALUES (:rule_name, :discount_type, :discount_value, NULL, :created_by)
                ");
                $rule->execute([
                    ':rule_name' => 'Approved request #' . (int)$requestId,
                    ':discount_type' => $request['discount_type'],
                    ':discount_value' => $request['discount_value'],
                    ':created_by' => (int)$reviewedBy,
                ]);
            }

            $this->conn->commit();
            return true;
        } catch (Throwable $e) {
            $this->conn->rollBack();
            throw $e;
        }
    }

    public function createRule($name, $type, $value, $maxSaleAmount, $createdBy) {
        $stmt = $this->conn->prepare("
            INSERT INTO discount_rules (rule_name, discount_type, discount_value, max_sale_amount, created_by)
            VALUES (:rule_name, :discount_type, :discount_value, :max_sale_amount, :created_by)
        ");
        return $stmt->execute([
            ':rule_name' => trim((string)$name),
            ':discount_type' => strtolower(trim((string)$type)),
            ':discount_value' => round((float)$value, 2),
            ':max_sale_amount' => $maxSaleAmount === '' || $maxSaleAmount === null ? null : round((float)$maxSaleAmount, 2),
            ':created_by' => (int)$createdBy,
        ]);
    }
}
?>
