<?php
defined('ABSPATH') or die('Direct access not allowed');

/**
 * VollstartRD_Ratings — Rating system.
 *
 * Types: 'internal' (staff rates customer), 'repair' (customer rates repair), 'business' (customer rates business)
 */
class VollstartRD_Ratings {

    private $MAIN;

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

    /**
     * Submit or update a rating.
     */
    public function submit(array $data): int {
        $db = $this->MAIN->getDB();
        $type = sanitize_text_field($data['type'] ?? '');
        $repairId = (int) ($data['repair_id'] ?? 0);
        $customerId = (int) ($data['customer_id'] ?? 0);

        // Check for existing rating (same type + repair or customer)
        $existing = $this->getExisting($type, $repairId, $customerId);

        $fields = [
            'repair_id'   => $repairId,
            'customer_id' => $customerId,
            'type'        => $type,
            'rating'      => max(1, min(5, (int) ($data['rating'] ?? 0))),
            'comment'     => sanitize_textarea_field($data['comment'] ?? ''),
            'phase'       => sanitize_text_field($data['phase'] ?? ''),
            'rated_by'    => sanitize_text_field($data['rated_by'] ?? ''),
        ];

        if ($existing) {
            $allowUpdate = $this->MAIN->getOptions()->isCheckboxActive('ratingAllowUpdate');
            $isPending = ($existing['rated_by'] ?? '') === 'pending' || (int) ($existing['rating'] ?? 0) === 0;
            if (!$allowUpdate && !$isPending && $type !== 'internal' && $type !== 'customer') return (int) $existing['id'];
            $fields['updated_at'] = current_time('mysql');
            $db->update('ratings', $fields, ['id' => (int) $existing['id']]);
            $this->recalcCustomerAvg($customerId);
            return (int) $existing['id'];
        }

        $fields['token'] = $this->generateToken();
        $fields['created_at'] = current_time('mysql');
        $id = $db->insert('ratings', $fields);
        $this->recalcCustomerAvg($customerId);
        return $id;
    }

    /**
     * Recalculate and cache customer average rating.
     */
    private function recalcCustomerAvg(int $customerId): void {
        if ($customerId <= 0) return;
        $avg = $this->getAverageForCustomer($customerId);
        $this->MAIN->getDB()->update('customers', ['avg_rating' => $avg], ['id' => $customerId]);
    }

    public function getExisting(string $type, int $repairId, int $customerId): ?array {
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');
        if ($type === 'business' || ($type === 'customer' && $repairId === 0)) {
            return $db->getRow("SELECT * FROM %i WHERE type = %s AND customer_id = %d AND repair_id = 0", $tbl, $type, $customerId);
        }
        return $db->getRow("SELECT * FROM %i WHERE type = %s AND repair_id = %d", $tbl, $type, $repairId);
    }

    public function getByToken(string $token): ?array {
        if (empty($token)) return null;
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');
        return $db->getRow("SELECT * FROM %i WHERE token = %s", $tbl, $token);
    }

    public function getForRepair(int $repairId): array {
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');
        return $db->getResults("SELECT * FROM %i WHERE repair_id = %d ORDER BY created_at ASC", $tbl, $repairId);
    }

    public function getForCustomer(int $customerId): array {
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');
        return $db->getResults("SELECT * FROM %i WHERE customer_id = %d ORDER BY created_at DESC", $tbl, $customerId);
    }

    public function getAverageForCustomer(int $customerId): float {
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');
        $avg = $db->getVar("SELECT AVG(rating) FROM %i WHERE customer_id = %d AND type = 'internal'", $tbl, $customerId);
        return $avg ? round((float) $avg, 1) : 0;
    }

    public function getAverageForBusiness(): float {
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');
        $avg = $db->getVar("SELECT AVG(rating) FROM %i WHERE type IN ('repair', 'business')", $tbl);
        return $avg ? round((float) $avg, 1) : 0;
    }

    /**
     * Generate rating URL for a repair.
     */
    public function getRatingUrl(int $repairId): string {
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');

        // Find or create rating entry with token
        $existing = $this->getExisting('repair', $repairId, 0);
        if ($existing && !empty($existing['token'])) {
            $token = $existing['token'];
        } else {
            // Create placeholder rating entry (rating=0, will be updated when customer rates)
            $repair = $this->MAIN->getRepairs()->getById($repairId);
            $customerId = $repair ? (int) $repair['customer_id'] : 0;
            $token = $this->generateToken();
            $db->insert('ratings', [
                'repair_id'   => $repairId,
                'customer_id' => $customerId,
                'type'        => 'repair',
                'rating'      => 0,
                'comment'     => '',
                'phase'       => '',
                'rated_by'    => 'pending',
                'token'       => $token,
                'created_at'  => current_time('mysql'),
            ]);
        }

        return home_url($this->MAIN->getFrontend()->getSlug() . '/rate/' . $token);
    }

    private function generateToken(): string {
        $db = $this->MAIN->getDB();
        $tbl = $db->getTabelle('ratings');
        do {
            $token = bin2hex(random_bytes(16));
            $existing = $db->getVar("SELECT id FROM %i WHERE token = %s", $tbl, $token);
        } while ($existing !== null);
        return $token;
    }
}
