from __future__ import annotations

import logging
from typing import Any

from spherepay_mcp.domain.value_objects import ApiError, ErrorCategory
from spherepay_mcp.ports.spherepay_gateway import SpherePayGateway

logger = logging.getLogger(__name__)


class CustomerOnboardingService:
    """Orchestrates customer creation and verification workflows."""

    def __init__(self, gateway: SpherePayGateway):
        self._gw = gateway

    async def onboard_customer(
        self,
        customer_type: str,
        email: str,
        phone: str,
        address: dict[str, Any],
        first_name: str | None = None,
        last_name: str | None = None,
        date_of_birth: str | None = None,
        business_information: dict[str, Any] | None = None,
        registered_address: dict[str, Any] | None = None,
        operating_address: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        """Create a customer and generate TOS + KYC verification links.

        Returns customer data with verification links for next steps.
        """
        if customer_type == "individual":
            payload: dict[str, Any] = {
                "type": "individual",
                "email": email,
                "phone": phone,
                "address": address,
            }
            if first_name:
                payload["firstName"] = first_name
            if last_name:
                payload["lastName"] = last_name
            if date_of_birth:
                payload["dateOfBirth"] = date_of_birth
        elif customer_type == "business":
            payload = {
                "type": "business",
                "email": email,
                "phone": phone,
            }
            if registered_address:
                payload["registeredAddress"] = registered_address
            if operating_address:
                payload["operatingAddress"] = operating_address
            if business_information:
                payload["businessInformation"] = business_information
        else:
            raise ApiError(
                category=ErrorCategory.VALIDATION,
                message=f"Invalid customer type: {customer_type}. Must be 'individual' or 'business'.",
                status_code=400,
            )

        customer = await self._gw.create_customer(payload)
        customer_id = customer.get("data", customer).get("id", "")

        tos_result = await self._gw.generate_tos_link(customer_id)
        kyc_result = await self._gw.generate_kyc_link(customer_id)

        return {
            "customer": customer.get("data", customer),
            "tos_link": tos_result.get("data", {}).get("link", tos_result),
            "kyc_link": kyc_result.get("data", {}).get("link", kyc_result),
            "next_steps": [
                "Customer must accept Terms of Service via the TOS link",
                "Customer must complete KYC verification via the KYC link",
                "After KYC, use verify_customer to complete the verification flow",
            ],
        }

    async def verify_customer(
        self,
        customer_id: str,
        phone_number: str | None = None,
        otp_code: str | None = None,
    ) -> dict[str, Any]:
        """Run verification sub-flows: OTP, face verification, and submission.

        If phone_number is provided without otp_code, sends OTP.
        If otp_code is provided, verifies OTP then proceeds to face verification.
        """
        if not phone_number and not otp_code:
            raise ApiError(
                category=ErrorCategory.VALIDATION,
                message="Either phone_number (to send OTP) or otp_code (to verify OTP) must be provided.",
                status_code=400,
            )

        results: dict[str, Any] = {"customer_id": customer_id, "steps_completed": []}

        if phone_number and not otp_code:
            await self._gw.send_otp(customer_id, {"phone": phone_number})
            results["otp_sent"] = True
            results["steps_completed"].append("otp_sent")
            results["next_steps"] = [
                "Provide the OTP code received via phone to verify_customer with otp_code parameter"
            ]
            return results

        if otp_code:
            await self._gw.verify_otp(customer_id, {"code": otp_code})
            results["steps_completed"].append("otp_verified")

        face_result = await self._gw.generate_face_verification_link(customer_id)
        results["face_verification_link"] = face_result.get("data", {}).get("link", face_result)
        results["steps_completed"].append("face_verification_link_generated")

        await self._gw.submit_verification(customer_id)
        results["verification_submitted"] = True
        results["steps_completed"].append("verification_submitted")
        results["next_steps"] = [
            "Verification has been submitted for review",
            "Use get_customer to check verification status",
        ]

        return results
