# Copyright (c) 2023-present Pi Dash Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.

# Third party imports
from rest_framework import serializers

# Module import
from pi_dash.db.models import Account, Profile, User, Workspace, WorkspaceMemberInvite
from pi_dash.utils.url import contains_url

from .base import BaseSerializer


class UserSerializer(BaseSerializer):
    def validate_first_name(self, value):
        if contains_url(value):
            raise serializers.ValidationError("First name cannot contain a URL.")
        return value

    def validate_last_name(self, value):
        if contains_url(value):
            raise serializers.ValidationError("Last name cannot contain a URL.")
        return value

    class Meta:
        model = User
        # Exclude password field from the serializer
        fields = [field.name for field in User._meta.fields if field.name != "password"]
        # Make all system fields and email read only
        read_only_fields = [
            "id",
            "username",
            "mobile_number",
            "email",
            "token",
            "created_at",
            "updated_at",
            "is_superuser",
            "is_staff",
            "is_managed",
            "last_active",
            "last_login_time",
            "last_logout_time",
            "last_login_ip",
            "last_logout_ip",
            "last_login_uagent",
            "last_location",
            "last_login_medium",
            "created_location",
            "is_bot",
            "is_password_autoset",
            "is_email_verified",
            "is_active",
            "token_updated_at",
        ]

        # If the user has already filled first name or last name then he is onboarded
        def get_is_onboarded(self, obj):
            return bool(obj.first_name) or bool(obj.last_name)


class UserMeSerializer(BaseSerializer):
    class Meta:
        model = User
        fields = [
            "id",
            "avatar",
            "cover_image",
            "avatar_url",
            "cover_image_url",
            "date_joined",
            "display_name",
            "email",
            "first_name",
            "last_name",
            "is_active",
            "is_bot",
            "is_email_verified",
            "user_timezone",
            "username",
            "is_password_autoset",
            "is_email_verified",
            "last_login_medium",
            "last_login_time",
        ]
        read_only_fields = fields


class UserMeSettingsSerializer(BaseSerializer):
    workspace = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ["id", "email", "workspace"]
        read_only_fields = fields

    def get_workspace(self, obj):
        workspace_invites = WorkspaceMemberInvite.objects.filter(email=obj.email).count()

        # profile
        profile = Profile.objects.get(user=obj)
        if (
            profile.last_workspace_id is not None
            and Workspace.objects.filter(
                pk=profile.last_workspace_id,
                workspace_member__member=obj.id,
                workspace_member__is_active=True,
            ).exists()
        ):
            workspace = Workspace.objects.filter(
                pk=profile.last_workspace_id,
                workspace_member__member=obj.id,
                workspace_member__is_active=True,
            ).first()
            logo_asset_url = workspace.logo_asset.asset_url if workspace.logo_asset is not None else ""
            return {
                "last_workspace_id": profile.last_workspace_id,
                "last_workspace_slug": (workspace.slug if workspace is not None else ""),
                "last_workspace_name": (workspace.name if workspace is not None else ""),
                "last_workspace_logo": (logo_asset_url),
                "fallback_workspace_id": profile.last_workspace_id,
                "fallback_workspace_slug": (workspace.slug if workspace is not None else ""),
                "invites": workspace_invites,
            }
        else:
            fallback_workspace = (
                Workspace.objects.filter(workspace_member__member_id=obj.id, workspace_member__is_active=True)
                .order_by("created_at")
                .first()
            )
            return {
                "last_workspace_id": None,
                "last_workspace_slug": None,
                "fallback_workspace_id": (fallback_workspace.id if fallback_workspace is not None else None),
                "fallback_workspace_slug": (fallback_workspace.slug if fallback_workspace is not None else None),
                "invites": workspace_invites,
            }


class UserLiteSerializer(BaseSerializer):
    class Meta:
        model = User
        fields = [
            "id",
            "first_name",
            "last_name",
            "avatar",
            "avatar_url",
            "is_bot",
            "display_name",
        ]
        read_only_fields = ["id", "is_bot"]


class UserAdminLiteSerializer(BaseSerializer):
    class Meta:
        model = User
        fields = [
            "id",
            "first_name",
            "last_name",
            "avatar",
            "avatar_url",
            "is_bot",
            "display_name",
            "email",
            "last_login_medium",
        ]
        read_only_fields = ["id", "is_bot"]


class ChangePasswordSerializer(serializers.Serializer):
    model = User

    """
    Serializer for password change endpoint.
    """
    old_password = serializers.CharField(required=True)
    new_password = serializers.CharField(required=True, min_length=8)
    confirm_password = serializers.CharField(required=True, min_length=8)

    def validate(self, data):
        if data.get("old_password") == data.get("new_password"):
            raise serializers.ValidationError({"error": "New password cannot be same as old password."})

        if data.get("new_password") != data.get("confirm_password"):
            raise serializers.ValidationError({"error": "Confirm password should be same as the new password."})

        return data


class ResetPasswordSerializer(serializers.Serializer):
    """
    Serializer for password change endpoint.
    """

    new_password = serializers.CharField(required=True, min_length=8)


class ProfileSerializer(BaseSerializer):
    class Meta:
        model = Profile
        fields = "__all__"
        read_only_fields = ["user"]


class AccountSerializer(BaseSerializer):
    class Meta:
        model = Account
        fields = "__all__"
        read_only_fields = ["user"]
