<?php
require_once 'config/database.php';

// ini_set('display_errors', 1);
// ini_set('display_startup_errors', 1);
// error_reporting(E_ALL);

/**
 * ContactsController
 *
 * Shared, org-wide contact directory (phone-style contact list).
 * Every authenticated user sees the same contacts; `created_by` is
 * stored for audit only and is NOT used to scope queries.
 */
class ContactsController {
    private $conn;

    // Columns that can be written via create/update/import.
    private $fields = [
        'first_name', 'last_name', 'phone', 'alt_phone', 'email',
        'company', 'job_title', 'group_name', 'notes'
    ];

    public function __construct() {
        $database = new Database();
        $this->conn = $database->getConnection();
    }

    private function validate($data, $required = []) {
        foreach ($required as $field) {
            if (!isset($data[$field]) || trim((string)$data[$field]) === '') {
                return ['status' => 'error', 'message' => "Missing required field: $field"];
            }
        }
        return null;
    }

    private function error($message) {
        return json_encode(['status' => 'error', 'message' => $message]);
    }

    // Normalize a phone number for duplicate comparison (digits + leading +).
    private function normalizePhone($phone) {
        $phone = trim((string)$phone);
        $plus  = strpos($phone, '+') === 0 ? '+' : '';
        return $plus . preg_replace('/\D+/', '', $phone);
    }

    // ────────────────────────────── CREATE ──────────────────────────────
    public function create($data, $userId) {
        $error = $this->validate($data, ['first_name', 'phone']);
        if ($error) return json_encode($error);

        $query = "INSERT INTO contacts
            (first_name, last_name, phone, alt_phone, email, company, job_title, group_name, is_favorite, notes, created_by)
            VALUES
            (:first_name, :last_name, :phone, :alt_phone, :email, :company, :job_title, :group_name, :is_favorite, :notes, :created_by)";
        $stmt = $this->conn->prepare($query);
        $stmt->bindValue(':first_name', trim($data['first_name']));
        $stmt->bindValue(':last_name',  $data['last_name']  ?? null);
        $stmt->bindValue(':phone',      trim($data['phone']));
        $stmt->bindValue(':alt_phone',  $data['alt_phone']  ?? null);
        $stmt->bindValue(':email',      $data['email']      ?? null);
        $stmt->bindValue(':company',    $data['company']    ?? null);
        $stmt->bindValue(':job_title',  $data['job_title']  ?? null);
        $stmt->bindValue(':group_name', $data['group_name'] ?? null);
        $stmt->bindValue(':is_favorite', !empty($data['is_favorite']) ? 1 : 0, PDO::PARAM_INT);
        $stmt->bindValue(':notes',      $data['notes']      ?? null);
        $stmt->bindValue(':created_by', $userId, PDO::PARAM_INT);

        if ($stmt->execute()) {
            return json_encode([
                'status'  => 'success',
                'message' => 'Contact created',
                'data'    => ['id' => (int)$this->conn->lastInsertId()]
            ]);
        }
        return $this->error('Failed to create contact');
    }

    // ────────────────────────────── LIST ──────────────────────────────
    public function getList($filters = []) {
        $where  = ["1=1"];
        $params = [];

        // Text search across name / phone / email / company
        if (!empty($filters['q'])) {
            $where[] = "(CONCAT(first_name,' ',COALESCE(last_name,'')) LIKE :q
                        OR phone LIKE :q OR email LIKE :q OR company LIKE :q)";
            $params[':q'] = '%' . $filters['q'] . '%';
        }
        if (!empty($filters['group'])) {
            $where[] = "group_name = :group";
            $params[':group'] = $filters['group'];
        }
        if (isset($filters['favorite']) && $filters['favorite'] !== '' && $filters['favorite'] !== 'all') {
            $where[] = "is_favorite = :favorite";
            $params[':favorite'] = ($filters['favorite'] === '1' || $filters['favorite'] === 'true' || $filters['favorite'] === 1) ? 1 : 0;
        }
        if (!empty($filters['status'])) {
            $where[] = "status = :status";
            $params[':status'] = $filters['status'];
        }

        $whereSql = implode(' AND ', $where);

        // Total count (for pagination)
        $countStmt = $this->conn->prepare("SELECT COUNT(*) FROM contacts WHERE $whereSql");
        $countStmt->execute($params);
        $total = (int)$countStmt->fetchColumn();

        // Pagination
        $limit  = isset($filters['limit'])  ? max(1, (int)$filters['limit'])  : 25;
        $offset = isset($filters['offset']) ? max(0, (int)$filters['offset']) : 0;

        $sql = "SELECT * FROM contacts
                WHERE $whereSql
                ORDER BY is_favorite DESC, first_name ASC, last_name ASC
                LIMIT :limit OFFSET :offset";
        $stmt = $this->conn->prepare($sql);
        foreach ($params as $k => $v) {
            $stmt->bindValue($k, $v);
        }
        $stmt->bindValue(':limit',  $limit,  PDO::PARAM_INT);
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->execute();
        $contacts = $stmt->fetchAll(PDO::FETCH_ASSOC);

        return json_encode([
            'status' => 'success',
            'data'   => ['contacts' => $contacts, 'total' => $total, 'limit' => $limit, 'offset' => $offset]
        ]);
    }

    // ────────────────────────────── GET ONE ──────────────────────────────
    public function getOne($id) {
        if (!$id) return $this->error('Contact id is required');
        $stmt = $this->conn->prepare("SELECT * FROM contacts WHERE id = :id");
        $stmt->bindValue(':id', $id, PDO::PARAM_INT);
        $stmt->execute();
        $contact = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$contact) return $this->error('Contact not found');
        return json_encode(['status' => 'success', 'data' => $contact]);
    }

    // ────────────────────────────── UPDATE ──────────────────────────────
    public function update($id, $data) {
        if (!$id) return $this->error('Contact id is required');

        $set = [];
        $params = [':id' => $id];
        foreach ($this->fields as $field) {
            if (array_key_exists($field, $data)) {
                $set[] = "$field = :$field";
                $params[":$field"] = $data[$field] !== '' ? $data[$field] : null;
            }
        }
        if (array_key_exists('is_favorite', $data)) {
            $set[] = "is_favorite = :is_favorite";
            $params[':is_favorite'] = !empty($data['is_favorite']) ? 1 : 0;
        }
        if (array_key_exists('status', $data) && $data['status'] !== '') {
            $set[] = "status = :status";
            $params[':status'] = $data['status'];
        }

        if (empty($set)) return $this->error('No fields to update');

        $sql = "UPDATE contacts SET " . implode(', ', $set) . " WHERE id = :id";
        $stmt = $this->conn->prepare($sql);
        if ($stmt->execute($params)) {
            return json_encode(['status' => 'success', 'message' => 'Contact updated']);
        }
        return $this->error('Failed to update contact');
    }

    // ────────────────────────────── DELETE ──────────────────────────────
    public function delete($id) {
        if (!$id) return $this->error('Contact id is required');
        $stmt = $this->conn->prepare("DELETE FROM contacts WHERE id = :id");
        $stmt->bindValue(':id', $id, PDO::PARAM_INT);
        if ($stmt->execute()) {
            return json_encode(['status' => 'success', 'message' => 'Contact deleted']);
        }
        return $this->error('Failed to delete contact');
    }

    // ────────────────────────────── TOGGLE FAVORITE ──────────────────────────────
    public function toggleFavorite($id) {
        if (!$id) return $this->error('Contact id is required');
        $stmt = $this->conn->prepare("UPDATE contacts SET is_favorite = 1 - is_favorite WHERE id = :id");
        $stmt->bindValue(':id', $id, PDO::PARAM_INT);
        if ($stmt->execute()) {
            $get = $this->conn->prepare("SELECT is_favorite FROM contacts WHERE id = :id");
            $get->bindValue(':id', $id, PDO::PARAM_INT);
            $get->execute();
            return json_encode(['status' => 'success', 'message' => 'Favorite updated', 'data' => ['is_favorite' => (int)$get->fetchColumn()]]);
        }
        return $this->error('Failed to update favorite');
    }

    // ────────────────────────────── BULK IMPORT ──────────────────────────────
    public function bulkImport($rows, $userId) {
        if (!is_array($rows) || count($rows) === 0) {
            return $this->error('No contacts to import');
        }

        // Pre-load existing normalized phones for duplicate detection.
        $existing = [];
        $stmt = $this->conn->query("SELECT phone FROM contacts");
        foreach ($stmt->fetchAll(PDO::FETCH_COLUMN) as $p) {
            $existing[$this->normalizePhone($p)] = true;
        }

        $insert = $this->conn->prepare("INSERT INTO contacts
            (first_name, last_name, phone, alt_phone, email, company, job_title, group_name, notes, created_by)
            VALUES
            (:first_name, :last_name, :phone, :alt_phone, :email, :company, :job_title, :group_name, :notes, :created_by)");

        $imported = 0;
        $skipped  = 0;
        $errors   = [];
        $seen     = [];

        foreach ($rows as $i => $row) {
            $rowNum    = $i + 1;
            $firstName = trim((string)($row['first_name'] ?? ''));
            $phone     = trim((string)($row['phone'] ?? ''));

            if ($firstName === '' || $phone === '') {
                $skipped++;
                $errors[] = ['row' => $rowNum, 'reason' => 'Missing first name or phone'];
                continue;
            }

            $norm = $this->normalizePhone($phone);
            if (isset($existing[$norm]) || isset($seen[$norm])) {
                $skipped++;
                $errors[] = ['row' => $rowNum, 'reason' => "Duplicate phone: $phone"];
                continue;
            }
            $seen[$norm] = true;

            $insert->bindValue(':first_name', $firstName);
            $insert->bindValue(':last_name',  $row['last_name']  ?? null);
            $insert->bindValue(':phone',      $phone);
            $insert->bindValue(':alt_phone',  $row['alt_phone']  ?? null);
            $insert->bindValue(':email',      $row['email']      ?? null);
            $insert->bindValue(':company',    $row['company']    ?? null);
            $insert->bindValue(':job_title',  $row['job_title']  ?? null);
            $insert->bindValue(':group_name', $row['group_name'] ?? null);
            $insert->bindValue(':notes',      $row['notes']      ?? null);
            $insert->bindValue(':created_by', $userId, PDO::PARAM_INT);

            if ($insert->execute()) {
                $imported++;
            } else {
                $skipped++;
                $errors[] = ['row' => $rowNum, 'reason' => 'Database insert failed'];
            }
        }

        return json_encode([
            'status'  => 'success',
            'message' => "Imported $imported contact(s), skipped $skipped",
            'data'    => ['imported' => $imported, 'skipped' => $skipped, 'errors' => $errors]
        ]);
    }

    // ────────────────────────────── GROUPS ──────────────────────────────
    public function getGroups() {
        $stmt = $this->conn->query("SELECT DISTINCT group_name FROM contacts
            WHERE group_name IS NOT NULL AND group_name <> '' ORDER BY group_name ASC");
        $groups = $stmt->fetchAll(PDO::FETCH_COLUMN);
        return json_encode(['status' => 'success', 'data' => $groups]);
    }

    // ────────────────────────────── STATISTICS ──────────────────────────────
    public function getStatistics() {
        $total     = (int)$this->conn->query("SELECT COUNT(*) FROM contacts")->fetchColumn();
        $favorites = (int)$this->conn->query("SELECT COUNT(*) FROM contacts WHERE is_favorite = 1")->fetchColumn();
        $groups    = (int)$this->conn->query("SELECT COUNT(DISTINCT group_name) FROM contacts
                        WHERE group_name IS NOT NULL AND group_name <> ''")->fetchColumn();

        return json_encode([
            'status' => 'success',
            'data'   => ['total' => $total, 'favorites' => $favorites, 'groups' => $groups]
        ]);
    }
}
