"""Copyright 2024 Everlasting Systems and Solutions LLC (www.myeverlasting.net).
All Rights Reserved.

No part of this software or any of its contents may be reproduced, copied, modified or adapted, without the prior written consent of the author, unless otherwise indicated for stand-alone materials.

For permission requests, write to the publisher at the email address below:
office@myeverlasting.net

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

"""

from pydantic import BaseModel, EmailStr, Field, model_validator, AnyHttpUrl
from typing_extensions import Self
from espy_pay.general.enums import TranxEnum, ISPEnum, TranxType
from typing import Optional, Union
from datetime import datetime


class TranxCreate(BaseModel):
    amount: int = Field(description="Amount must be greater than 2000 if NGN 25 if USD")
    description: str | None = None
    currency: str = "NGN"
    payee_id: int  # Appuser ID field
    first_name: str | None = None
    last_name: str | None = None
    email: EmailStr | None = None
    phone: Optional[str] = None
    detail: Union[dict, str] | None = None  # Can be dict or string for flexibility
    tranx_type: TranxType = TranxType.OTHERS
    receipt: str | None = None

    @model_validator(mode="after")
    def check_email_or_phone(self):
        payee_id = self.payee_id
        first_name = self.first_name
        last_name = self.last_name
        email = self.email
        if not payee_id:
            if not all([first_name, last_name, email]):
                raise ValueError(
                    "if payee_id is not provided, first_name, last_name and email must be provided"
                )
        return self


class TranxDto(TranxCreate):
    ref: int | None = None  # ref is generated by backend
    isp: ISPEnum | None = None
    stripe_payment_method: str | None = None
    status: TranxEnum = TranxEnum.PENDING
    createdOn: Optional[datetime] = None
    modifiedOn: Optional[datetime] = None
    callback_url: AnyHttpUrl | None = None
    stripeId: str | None = None

    @model_validator(mode="after")
    def validate_stripe_payment_amount(self) -> Self:
        isp = self.isp
        method = self.stripe_payment_method
        if isp == ISPEnum.STRIPE and method is None:
            raise ValueError(
                "stripe_payment_method must be provided when isp is 'STRIPE'"
            )
        return self


class TranxIntent(BaseModel):
    id: str
    payment_method: str
    return_url: str
