<?php

namespace PloverCRM\Core\CRM\Schemas;

/**
 * Contact Schema
 * 
 * Defines the standard structure for contact data across all CRM providers
 */
class ContactSchema
{
    /**
     * Required fields that must be present
     */
    const REQUIRED_FIELDS = [
        'id',
        'created_at',
    ];

    /**
     * All standard fields with their types
     */
    const FIELDS = [
        'id' => 'integer',
        'email' => 'string',
        'first_name' => 'string',
        'last_name' => 'string',
        'full_name' => 'string',
        'status' => 'string',
        'phone' => 'string',
        'city' => 'string',
        'state' => 'string',
        'country' => 'string',
        'postal_code' => 'string',
        'hash' => 'string',
        'plover_crm_avatar' => 'string',
        'custom_fields' => 'array',
        'last_note' => 'object|null',
        'tags' => 'array',
        'lists' => 'array',
        'created_at' => 'string',
        'updated_at' => 'string',
    ];

    /**
     * Validate contact data
     * 
     * @param array $data
     * @return array ['valid' => bool, 'errors' => array]
     */
    public static function validate(array $data): array
    {
        $errors = [];

        // Check required fields
        foreach (self::REQUIRED_FIELDS as $field) {
            if (!isset($data[$field]) || $data[$field] === null || $data[$field] === '') {
                $errors[] = "Required field '{$field}' is missing or empty";
            }
        }

        // Validate field types
        foreach (self::FIELDS as $field => $type) {
            if (!isset($data[$field])) {
                continue; // Skip optional fields
            }

            $valid = self::validateType($data[$field], $type);
            if (!$valid) {
                $errors[] = "Field '{$field}' must be of type '{$type}', got '" . gettype($data[$field]) . "'";
            }
        }

        // Validate custom_fields structure
        if (isset($data['custom_fields']) && is_array($data['custom_fields'])) {
            foreach ($data['custom_fields'] as $index => $field) {
                if (!is_array($field)) {
                    $errors[] = "custom_fields[{$index}] must be an array";
                    continue;
                }

                $missing = [];
                if (!isset($field['label'])) $missing[] = 'label';
                if (!isset($field['key'])) $missing[] = 'key';
                if (!isset($field['value'])) $missing[] = 'value';

                if (!empty($missing)) {
                    $fieldInfo = isset($field['key']) ? " (key: {$field['key']})" : '';
                    $errors[] = "custom_fields[{$index}]{$fieldInfo} must have 'label', 'key', and 'value' properties. Missing: " . implode(', ', $missing);
                }
            }
        }

        // Validate last_note structure
        if (isset($data['last_note']) && $data['last_note'] !== null) {
            if (!is_object($data['last_note']) && !is_array($data['last_note'])) {
                $errors[] = "last_note must be an object/array or null";
            }
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
        ];
    }

    /**
     * Normalize contact data to standard format
     * 
     * @param array $data
     * @return array
     */
    public static function normalize(array $data): array
    {
        $normalized = [
            'id' => (int) ($data['id'] ?? 0),
            'email' => (string) ($data['email'] ?? ''),
            'first_name' => (string) ($data['first_name'] ?? ''),
            'last_name' => (string) ($data['last_name'] ?? ''),
            'phone' => (string) ($data['phone'] ?? ''),
            'city' => (string) ($data['city'] ?? ''),
            'state' => (string) ($data['state'] ?? ''),
            'country' => (string) ($data['country'] ?? ''),
            'postal_code' => (string) ($data['postal_code'] ?? ''),
            'hash' => (string) ($data['hash'] ?? ''),
            'plover_crm_avatar' => (string) ($data['plover_crm_avatar'] ?? ''),
            'custom_fields' => (array) ($data['custom_fields'] ?? []),
            'last_note' => $data['last_note'] ?? null,
            'tags' => (array) ($data['tags'] ?? []),
            'lists' => (array) ($data['lists'] ?? []),
            'created_at' => (string) ($data['created_at'] ?? ''),
            'updated_at' => (string) ($data['updated_at'] ?? ''),
        ];

        // Only include status if provided (FluentCRM uses it, PloverCRM doesn't)
        if (isset($data['status'])) {
            $normalized['status'] = (string) $data['status'];
        }

        return $normalized;
    }

    /**
     * Validate field type
     * 
     * @param mixed $value
     * @param string $type
     * @return bool
     */
    private static function validateType($value, string $type): bool
    {
        // Handle union types (e.g., "object|null")
        if (strpos($type, '|') !== false) {
            $types = explode('|', $type);
            foreach ($types as $t) {
                if (self::validateType($value, trim($t))) {
                    return true;
                }
            }
            return false;
        }

        switch ($type) {
            case 'integer':
                return is_int($value) || is_numeric($value);
            case 'string':
                return is_string($value);
            case 'array':
                return is_array($value);
            case 'object':
                return is_object($value) || is_array($value);
            case 'null':
                return $value === null;
            default:
                return false;
        }
    }
}
