"""
SendCraft SDK Client
"""

import requests
from datetime import datetime
from typing import Dict, List, Optional, Any
from .exceptions import (
    SendCraftError,
    UnauthorizedError,
    ForbiddenError,
    NotFoundError,
    RateLimitError,
    ServerError
)


class SendCraft:
    """Official SendCraft client for Python"""

    def __init__(self, api_key: str, base_url: str = None, timeout: int = 30):
        """
        Initialize SendCraft client

        Args:
            api_key (str): Your SendCraft API key (SENDCRAFT_API_KEY)
            base_url (str): API base URL (default: https://sendcraft.online/api)
            timeout (int): Request timeout in seconds (default: 30)
        """
        if not api_key:
            raise ValueError("API key is required")

        self.api_key = api_key
        self.base_url = base_url or "https://sendcraft.online/api"
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers.update({
            "x-api-key": self.api_key,
            "Content-Type": "application/json"
        })

    def _request(self, method: str, endpoint: str, data: Dict = None, params: Dict = None) -> Dict:
        url = f"{self.base_url}{endpoint}"

        try:
            response = self.session.request(
                method=method,
                url=url,
                json=data,
                params=params,
                timeout=self.timeout
            )

            if response.status_code == 401:
                raise UnauthorizedError("Invalid or missing API key")
            elif response.status_code == 403:
                raise ForbiddenError("You don't have permission to access this resource")
            elif response.status_code == 404:
                raise NotFoundError("The requested resource was not found")
            elif response.status_code == 429:
                raise RateLimitError("Too many requests. Please wait before retrying")
            elif response.status_code >= 500:
                raise ServerError(f"Server error: {response.status_code}")
            elif response.status_code >= 400:
                raise SendCraftError(f"Request failed: {response.status_code}")

            return response.json()

        except requests.exceptions.Timeout:
            raise SendCraftError("Request timeout")
        except requests.exceptions.ConnectionError:
            raise SendCraftError("Connection error")
        except requests.exceptions.RequestException as e:
            raise SendCraftError(f"Request failed: {str(e)}")

    def send_email(self, to_email: str, subject: str, html_content: str,
                   to_name: str = None, plain_text_content: str = None,
                   from_email: str = None, from_name: str = None, reply_to: str = None) -> Dict:
        payload = {
            "toEmail": to_email,
            "subject": subject,
            "htmlContent": html_content,
            "toName": to_name,
            "plainTextContent": plain_text_content,
            "fromEmail": from_email,
            "fromName": from_name,
            "replyTo": reply_to
        }
        return self._request("POST", "/emails/send", data=payload)

    def send_bulk_emails(self, emails: List[Dict], subject: str, html_content: str,
                         from_email: str, plain_text_content: str = None, from_name: str = None) -> Dict:
        payload = {
            "emails": emails,
            "subject": subject,
            "htmlContent": html_content,
            "fromEmail": from_email,
            "plainTextContent": plain_text_content,
            "fromName": from_name
        }
        return self._request("POST", "/emails/send-bulk", data=payload)

    def schedule_email(self, to_email: str, subject: str, html_content: str,
                       scheduled_time: datetime, from_email: str = None,
                       to_name: str = None, from_name: str = None) -> Dict:
        payload = {
            "toEmail": to_email,
            "subject": subject,
            "htmlContent": html_content,
            "scheduledTime": scheduled_time.isoformat() if isinstance(scheduled_time, datetime) else scheduled_time,
            "fromEmail": from_email,
            "toName": to_name,
            "fromName": from_name
        }
        return self._request("POST", "/emails/schedule", data=payload)

    def get_email_stats(self) -> Dict:
        return self._request("GET", "/emails/stats/summary")

    def create_campaign(self, name: str, subject: str, from_email: str,
                        html_content: str, recipients: List[str] = None,
                        from_name: str = None, send_immediately: bool = False) -> Dict:
        payload = {
            "name": name,
            "subject": subject,
            "fromEmail": from_email,
            "htmlContent": html_content,
            "recipients": recipients,
            "fromName": from_name,
            "sendImmediately": send_immediately
        }
        return self._request("POST", "/campaigns", data=payload)

    def get_campaigns(self, limit: int = 50) -> Dict:
        return self._request("GET", "/campaigns", params={"limit": limit})

    def get_campaign(self, campaign_id: str) -> Dict:
        return self._request("GET", f"/campaigns/{campaign_id}")

    def send_campaign(self, campaign_id: str) -> Dict:
        return self._request("POST", f"/campaigns/{campaign_id}/send")

    def create_template(self, name: str, subject: str, html_content: str,
                        category: str = None, variables: List[str] = None) -> Dict:
        payload = {
            "name": name,
            "subject": subject,
            "htmlContent": html_content,
            "category": category,
            "variables": variables
        }
        return self._request("POST", "/templates", data=payload)

    def get_templates(self) -> Dict:
        return self._request("GET", "/templates")

    def get_template(self, template_id: str) -> Dict:
        return self._request("GET", f"/templates/{template_id}")

    def update_template(self, template_id: str, **kwargs) -> Dict:
        return self._request("PUT", f"/templates/{template_id}", data=kwargs)

    def delete_template(self, template_id: str) -> Dict:
        return self._request("DELETE", f"/templates/{template_id}")

    def add_subscriber(self, email: str, list_id: str, first_name: str = None,
                       last_name: str = None, custom_fields: Dict = None) -> Dict:
        payload = {
            "email": email,
            "listId": list_id,
            "firstName": first_name,
            "lastName": last_name,
            "customFields": custom_fields
        }
        return self._request("POST", "/subscribers/add", data=payload)

    def get_subscribers(self, list_id: str = None, limit: int = 50) -> Dict:
        return self._request("GET", "/subscribers", params={"listId": list_id, "limit": limit})

    def remove_subscriber(self, subscriber_id: str) -> Dict:
        return self._request("DELETE", f"/subscribers/{subscriber_id}")

    def create_webhook(self, url: str, events: List[str], name: str = None) -> Dict:
        payload = {"url": url, "events": events, "name": name}
        return self._request("POST", "/webhooks", data=payload)

    def get_webhooks(self) -> Dict:
        return self._request("GET", "/webhooks")

    def delete_webhook(self, webhook_id: str) -> Dict:
        return self._request("DELETE", f"/webhooks/{webhook_id}")

    def get_analytics(self, campaign_id: str) -> Dict:
        return self._request("GET", f"/analytics/campaign/{campaign_id}")

    def get_billing_info(self) -> Dict:
        return self._request("GET", "/billing/info")

    def get_account(self) -> Dict:
        return self._request("GET", "/account")

    def update_account(self, **kwargs) -> Dict:
        return self._request("PUT", "/account", data=kwargs)

    def change_password(self, old_password: str, new_password: str) -> Dict:
        return self._request("POST", "/account/change-password", data={
            "oldPassword": old_password,
            "newPassword": new_password
        })
