# Part of Odoo. See LICENSE file for full copyright and licensing details.

import uuid

from odoo.addons.fusion_clover import const


def generate_idempotency_key():
    """Generate a unique idempotency key for Clover API requests."""
    return str(uuid.uuid4())


def build_ecom_url(endpoint, is_test=False):
    """Build a full Clover Ecommerce API URL.

    :param str endpoint: The API endpoint path (e.g., 'v1/charges').
    :param bool is_test: Whether to use the sandbox environment.
    :return: The full API URL.
    :rtype: str
    """
    base = const.ECOM_BASE_URL_TEST if is_test else const.ECOM_BASE_URL
    return f"{base}/{endpoint}"


def build_platform_url(endpoint, merchant_id=None, is_test=False):
    """Build a full Clover Platform API URL.

    :param str endpoint: The API endpoint path.
    :param str merchant_id: The merchant ID (optional).
    :param bool is_test: Whether to use the sandbox environment.
    :return: The full API URL.
    :rtype: str
    """
    base = const.API_BASE_URL_TEST if is_test else const.API_BASE_URL
    if merchant_id:
        return f"{base}/v3/merchants/{merchant_id}/{endpoint}"
    return f"{base}/{endpoint}"


def build_ecom_headers(api_key, idempotency_key=None):
    """Build the standard HTTP headers for a Clover Ecommerce API request.

    :param str api_key: The Clover API key (Bearer token).
    :param str idempotency_key: Optional unique key for idempotency.
    :return: The request headers dict.
    :rtype: dict
    """
    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': f'Bearer {api_key}',
    }
    if idempotency_key:
        headers['idempotency-key'] = idempotency_key
    return headers


def format_clover_amount(amount, currency):
    """Convert a major currency amount to Clover's minor units (cents).

    :param float amount: The amount in major currency units.
    :param recordset currency: The currency record.
    :return: The amount in minor currency units (integer).
    :rtype: int
    """
    decimals = const.CURRENCY_DECIMALS.get(currency.name, 2)
    return int(round(amount * (10 ** decimals)))


def parse_clover_amount(minor_amount, currency):
    """Convert Clover's minor currency units back to major units.

    :param int minor_amount: The amount in minor currency units.
    :param recordset currency: The currency record.
    :return: The amount in major currency units.
    :rtype: float
    """
    decimals = const.CURRENCY_DECIMALS.get(currency.name, 2)
    return minor_amount / (10 ** decimals)


def extract_card_details(source):
    """Extract card details from a Clover charge source object.

    :param dict source: The Clover source object from a charge response.
    :return: Dict with card brand, last4, expiration.
    :rtype: dict
    """
    if not source:
        return {}

    brand_raw = source.get('brand', '')
    brand_code = const.CARD_BRAND_MAPPING.get(brand_raw, 'card')

    return {
        'brand': brand_code,
        'last4': str(source.get('last4', '')),
        'exp_month': source.get('exp_month'),
        'exp_year': source.get('exp_year'),
        'first6': str(source.get('first6', '')),
    }


def get_clover_status(status_str):
    """Map a Clover charge status string to an Odoo transaction state.

    :param str status_str: The Clover charge status.
    :return: The corresponding Odoo payment state.
    :rtype: str
    """
    for odoo_state, clover_statuses in const.STATUS_MAPPING.items():
        if status_str in clover_statuses:
            return odoo_state
    return 'error'


def build_charge_payload(amount, currency, source_token, capture=True,
                         description='', ecomind='ecom',
                         external_reference_id='', receipt_email='',
                         metadata=None):
    """Build a Clover charge creation payload.

    :param float amount: The charge amount in major currency units.
    :param recordset currency: The currency record.
    :param str source_token: The Clover card token.
    :param bool capture: Whether to capture immediately (True) or pre-auth (False).
    :param str description: Optional charge description.
    :param str ecomind: 'ecom' for customer-initiated, 'moto' for merchant-initiated.
    :param str external_reference_id: External reference (max 12 chars).
    :param str receipt_email: Email to send receipt to.
    :param dict metadata: Optional key-value metadata.
    :return: The Clover-formatted charge payload.
    :rtype: dict
    """
    minor_amount = format_clover_amount(amount, currency)

    payload = {
        'amount': minor_amount,
        'currency': currency.name.lower(),
        'source': source_token,
        'capture': capture,
        'ecomind': ecomind,
    }

    if description:
        payload['description'] = description
    if external_reference_id:
        payload['external_reference_id'] = external_reference_id[:12]
    if receipt_email:
        payload['receipt_email'] = receipt_email
    if metadata:
        payload['metadata'] = metadata

    return payload


def build_refund_payload(charge_id, amount=None, currency=None, reason=''):
    """Build a Clover refund payload.

    :param str charge_id: The Clover charge ID to refund.
    :param float amount: Optional partial refund amount in major currency units.
    :param recordset currency: Optional currency record (needed for partial refunds).
    :param str reason: Optional reason for the refund.
    :return: The Clover-formatted refund payload.
    :rtype: dict
    """
    payload = {
        'charge': charge_id,
    }

    if amount is not None and currency:
        payload['amount'] = format_clover_amount(amount, currency)

    if reason:
        payload['reason'] = reason

    return payload
