<?php

namespace PloverCRM\Core\Services;

/**
 * Shared business information service.
 *
 * Stores workspace-level business details in a dedicated option so both the
 * website and mobile app can read and update the same source of truth.
 */
class BusinessInformationService
{
    const OPTION_NAME = 'plover_crm_business_information';
    const LOGO_UPLOAD_FIELD = 'logo';
    const LOGO_MAX_BYTES = 2097152;

    /**
     * Get the current business information or null when empty.
     */
    public static function get(): ?array
    {
        return self::normalizeForApi(self::getStoredOption());
    }

    /**
     * Update the shared business information.
     *
     * @param array $data
     * @return array|null
     */
    public static function update(array $data): ?array
    {
        $stored = self::getStoredOption();
        $sanitized = self::sanitize($data);
        $logoAttachmentId = self::normalizeAttachmentId($stored['logo_attachment_id'] ?? null);

        if ($logoAttachmentId > 0) {
            $sanitized['logo_attachment_id'] = $logoAttachmentId;
        }

        if (self::isEmptyStorage($sanitized)) {
            delete_option(self::OPTION_NAME);
            return null;
        }

        update_option(self::OPTION_NAME, $sanitized);

        return self::normalizeForApi($sanitized);
    }

    /**
     * Replace the shared business logo.
     *
     * @param array $file
     * @return array|\WP_Error|null
     */
    public static function replaceLogo(array $file)
    {
        if (empty($file) || !is_array($file) || empty($file['tmp_name'])) {
            return new \WP_Error('business_logo_missing', 'Choose a logo image to upload.');
        }

        if (!empty($file['error']) && (int) $file['error'] !== UPLOAD_ERR_OK) {
            return new \WP_Error('business_logo_upload_failed', 'The selected logo could not be uploaded.');
        }

        if (!empty($file['size']) && (int) $file['size'] > self::LOGO_MAX_BYTES) {
            return new \WP_Error('business_logo_too_large', 'Business logos must be 2 MB or smaller.');
        }

        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';

        $existing = self::getStoredOption();
        $businessName = trim((string) ($existing['businessName'] ?? ''));
        $attachmentId = media_handle_upload(
            self::LOGO_UPLOAD_FIELD,
            0,
            [
                'post_title' => sprintf(
                    '%s business logo',
                    $businessName !== '' ? $businessName : get_bloginfo('name')
                ),
            ],
            [
                'test_form' => false,
                'mimes' => self::getAllowedLogoMimeTypes(),
            ]
        );

        if (is_wp_error($attachmentId)) {
            return new \WP_Error(
                'business_logo_upload_failed',
                $attachmentId->get_error_message() ?: 'The selected logo could not be uploaded.'
            );
        }

        $previousAttachmentId = self::normalizeAttachmentId($existing['logo_attachment_id'] ?? null);
        $next = self::sanitize($existing);
        $next['logo_attachment_id'] = (int) $attachmentId;
        $next['updatedAt'] = self::currentTimestamp();

        update_option(self::OPTION_NAME, $next);
        self::deleteLogoAttachmentId($previousAttachmentId, (int) $attachmentId);

        return self::normalizeForApi($next);
    }

    /**
     * Remove the shared business logo.
     */
    public static function removeLogo(): bool
    {
        $stored = self::getStoredOption();
        $currentAttachmentId = self::normalizeAttachmentId($stored['logo_attachment_id'] ?? null);

        if ($currentAttachmentId <= 0) {
            return true;
        }

        $next = self::sanitize($stored);

        if (self::isEmptyStorage($next)) {
            delete_option(self::OPTION_NAME);
        } else {
            update_option(self::OPTION_NAME, $next);
        }

        self::deleteLogoAttachmentId($currentAttachmentId);

        return true;
    }

    /**
     * Normalize and sanitize the business information payload.
     *
     * @param array $data
     * @return array
     */
    public static function sanitize(array $data): array
    {
        $businessName = sanitize_text_field($data['businessName'] ?? '');
        $businessAddress = sanitize_textarea_field($data['businessAddress'] ?? '');
        $businessEmail = sanitize_email($data['businessEmail'] ?? '');

        $normalized = [
            'businessName' => trim($businessName),
            'businessAddress' => trim($businessAddress),
            'businessEmail' => trim($businessEmail),
        ];

        $normalized['updatedAt'] = self::isEmpty($normalized)
            ? ''
            : self::currentTimestamp();

        return $normalized;
    }

    /**
     * Whether the normalized business information contains any usable value.
     *
     * @param array|null $data
     * @return bool
     */
    public static function isEmpty(?array $data): bool
    {
        if (!$data) {
            return true;
        }

        return empty($data['businessName'])
            && empty($data['businessAddress'])
            && empty($data['businessEmail'])
            && empty($data['businessLogoUrl'])
            && self::normalizeAttachmentId($data['logo_attachment_id'] ?? null) <= 0;
    }

    private static function getStoredOption(): array
    {
        $value = get_option(self::OPTION_NAME, null);

        return is_array($value) ? $value : [];
    }

    private static function normalizeForApi(array $value): ?array
    {
        $logoAttachmentId = self::normalizeAttachmentId($value['logo_attachment_id'] ?? null);
        $sanitized = [
            'businessName' => trim(sanitize_text_field($value['businessName'] ?? '')),
            'businessAddress' => trim(sanitize_textarea_field($value['businessAddress'] ?? '')),
            'businessEmail' => trim(sanitize_email($value['businessEmail'] ?? '')),
            'businessLogoUrl' => $logoAttachmentId > 0
                ? (wp_get_attachment_image_url($logoAttachmentId, 'full') ?: null)
                : null,
            'updatedAt' => sanitize_text_field($value['updatedAt'] ?? ''),
        ];

        return self::isEmpty($sanitized) ? null : $sanitized;
    }

    private static function isEmptyStorage(?array $data): bool
    {
        if (!$data) {
            return true;
        }

        return self::isEmpty($data)
            && self::normalizeAttachmentId($data['logo_attachment_id'] ?? null) <= 0;
    }

    private static function normalizeAttachmentId($value): int
    {
        return is_numeric($value) ? max(0, (int) $value) : 0;
    }

    private static function getAllowedLogoMimeTypes(): array
    {
        return [
            'jpg|jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'webp' => 'image/webp',
        ];
    }

    private static function deleteLogoAttachmentId(int $attachmentId, int $skipAttachmentId = 0): void
    {
        if ($attachmentId <= 0 || $attachmentId === $skipAttachmentId) {
            return;
        }

        wp_delete_attachment($attachmentId, true);
    }

    /**
     * Generate a stable ISO-8601 timestamp for API/mobile consumption.
     */
    private static function currentTimestamp(): string
    {
        return current_datetime()->setTimezone(new \DateTimeZone('UTC'))->format(DATE_ATOM);
    }
}
