from django.contrib import admin, messages
from django.contrib.auth.admin import UserAdmin
from django.utils import timezone
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
from django.utils.html import escape
from django.urls import reverse, path
from django.utils.safestring import mark_safe
from django.shortcuts import render
from django.db.models import Avg
from datetime import timedelta, datetime

from biz.models import Prospect, ProspectGroup

from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, Court, DateInterval, FailedApiCall, Log, DeviceToken, DrawLog, UnregisteredTeam, UnregisteredPlayer, Image
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .filters import TeamScoreTournamentListFilter, MatchTournamentListFilter, SimpleTournamentListFilter, MatchTypeListFilter, SimpleIndexListFilter, StartDateRangeFilter, UserWithEventsFilter, UserWithPurchasesFilter, UserWithProspectFilter

from sync.admin import SyncedObjectAdmin
import logging


logger = logging.getLogger(__name__)

class CustomUserAdmin(UserAdmin):
    form = CustomUserChangeForm
    add_form = CustomUserCreationForm
    model = CustomUser
    search_fields = ['username', 'email', 'phone', 'first_name', 'last_name', 'licence_id']
    filter_horizontal = ('clubs',)
    actions = ['convert_to_prospect', 'create_group']

    list_display = ['email', 'first_name', 'last_name', 'username', 'date_joined', 'latest_event_club_name', 'is_active', 'event_count', 'origin', 'registration_payment_mode', 'licence_id']
    list_filter = ['is_active', 'origin', UserWithEventsFilter, UserWithPurchasesFilter, UserWithProspectFilter]
    ordering = ['-date_joined']
    raw_id_fields = ['agents']
    fieldsets = [
        (None, {'fields': ['id', 'username', 'email', 'password', 'first_name', 'last_name', 'is_active']}),
        ('Permissions', {'fields': ['is_staff', 'is_superuser', 'groups', 'user_permissions']}),
        ('Personal Info', {'fields': ['registration_payment_mode', 'clubs', 'country', 'phone', 'licence_id', 'umpire_code']}),
        ('Tournament Settings', {'fields': [
            'summons_message_body', 'summons_message_signature', 'summons_available_payment_methods',
            'summons_display_format', 'summons_display_entry_fee', 'summons_use_full_custom_message',
            'match_formats_default_duration', 'bracket_match_format_preference', 'group_stage_match_format_preference',
            'loser_bracket_match_format_preference', 'device_id', 'loser_bracket_mode', 'origin', 'agents', 'should_synchronize', 'can_synchronize'
        ]}),
    ]

    add_fieldsets = [
        (
            None,
            {
                "classes": ["wide"],
                "fields": ['username', 'email', 'password1', 'password2', 'first_name', 'last_name', 'clubs', 'country', 'phone', 'licence_id', 'umpire_code', 'groups'],
            },
        ),
    ]

    def save_model(self, request, obj, form, change):
        obj.last_update = timezone.now()
        super().save_model(request, obj, form, change)

    def create_group(self, request, queryset):
        prospects = []
        source_value = f"auto_created_{datetime.now().strftime('%Y-%m-%d_%H:%M')}"
        for user in queryset:
            prospect = Prospect.objects.filter(email=user.email).first()
            if prospect:
                prospects.append(prospect)
            else:
                prospect = Prospect.objects.create(
                    first_name=user.first_name,
                    last_name=user.last_name,
                    email=user.email,
                    phone=user.phone,
                    official_user=user,
                    source=source_value
                )
                prospects.append(prospect)
        prospect_group = ProspectGroup.objects.create(
            name=f"{datetime.now().strftime('%Y-%m-%d_%H:%M')}",
        )
        prospect_group.prospects.add(*prospects)
        messages.success(request, f'Created prospect group {prospect_group.name} with {queryset.count()} prospects')

    create_group.short_description = "Create group with selection"

    def convert_to_prospect(self, request, queryset):
        created_count = 0
        skipped_count = 0
        source_value = f"user_conversion_{datetime.now().strftime('%Y-%m-%d_%H:%M')}"

        for user in queryset:
            if user.email and Prospect.objects.filter(email=user.email).exists():
                skipped_count += 1
                continue

            prospect = Prospect.objects.create(
                first_name=user.first_name,
                last_name=user.last_name,
                email=user.email,
                phone=user.phone,
                official_user=user,
                source=source_value
            )
            created_count += 1

        if created_count > 0:
            messages.success(request, f'{created_count} prospect(s) successfully created.')
        if skipped_count > 0:
            messages.warning(request, f'{skipped_count} user(s) skipped (prospect with same email already exists).')

    convert_to_prospect.short_description = "Convert selected users to prospects"

class EventAdmin(SyncedObjectAdmin):
    list_display = ['creation_date', 'name', 'club', 'creator', 'tenup_id', 'display_images']
    list_filter = ['creator', 'club', 'tenup_id']
    search_fields = ['name', 'club__name', 'creator__email']
    raw_id_fields = ['related_user', 'creator', 'club']
    ordering = ['-creation_date']
    readonly_fields = ['display_images_preview']

    fieldsets = [
        (None, {'fields': ['last_update', 'related_user', 'name', 'club', 'creator', 'creation_date', 'tenup_id']}),
        ('Images', {'fields': ['display_images_preview'], 'classes': ['collapse']}),
    ]

    def display_images(self, obj):
        count = obj.images.count()
        return count if count > 0 else '-'
    display_images.short_description = 'Images'

    def display_images_preview(self, obj):
        html = '<div style="display: flex; flex-wrap: wrap; gap: 10px;">'
        for image in obj.images.all():
            html += f'''
            <div style="text-align: center; margin-bottom: 15px;">
                <img src="{image.image.url}" style="max-width: 150px; max-height: 150px; object-fit: contain;" />
                <p style="margin: 5px 0 0 0; font-size: 12px;">
                    <strong>{image.title or "Untitled"}</strong><br>
                    Type: {image.get_image_type_display()}<br>
                </p>
            </div>
            '''
        html += '</div>'
        if not obj.images.exists():
            html = '<p>No images uploaded for this event.</p>'
        return mark_safe(html)
    display_images_preview.short_description = 'Images Preview'

class TournamentAdmin(SyncedObjectAdmin):
    list_display = ['display_name', 'event', 'is_private', 'start_date', 'payment', 'creator', 'is_canceled']
    list_filter = [StartDateRangeFilter, 'is_deleted', 'event__creator']
    ordering = ['-start_date']
    search_fields = ['id', 'federal_level_category']
    raw_id_fields = ['last_updated_by', 'event']

    def dashboard_view(self, request):
        """Tournament dashboard view with comprehensive statistics"""

        # Calculate date ranges
        now = timezone.now()
        today = now.date()
        week_start = today - timedelta(days=today.weekday())  # Monday of this week
        week_end = week_start + timedelta(days=6)  # Sunday of this week
        month_start = today.replace(day=1)  # First day of current month

        # Tournament statistics - tournaments starting TODAY
        tournaments_today = Tournament.objects.filter(
            start_date__date=today
        ).exclude(is_deleted=True)

        tournaments_today_private = tournaments_today.filter(is_private=True).count()
        tournaments_today_public = tournaments_today.filter(is_private=False).count()
        tournaments_today_total = tournaments_today.count()

        # Tournament statistics - tournaments starting THIS WEEK
        tournaments_this_week = Tournament.objects.filter(
            start_date__date__gte=week_start,
            start_date__date__lte=week_end
        ).exclude(is_deleted=True)

        tournaments_week_private = tournaments_this_week.filter(is_private=True).count()
        tournaments_week_public = tournaments_this_week.filter(is_private=False).count()
        tournaments_week_total = tournaments_this_week.count()

        # Tournament statistics - tournaments starting THIS MONTH
        tournaments_this_month = Tournament.objects.filter(
            start_date__date__gte=month_start,
            start_date__date__lte=today + timedelta(days=31 - today.day)  # End of current month
        ).exclude(is_deleted=True)

        tournaments_month_private = tournaments_this_month.filter(is_private=True).count()
        tournaments_month_public = tournaments_this_month.filter(is_private=False).count()
        tournaments_month_total = tournaments_this_month.count()

        # All time tournament statistics
        all_tournaments = Tournament.objects.exclude(is_deleted=True)
        tournaments_all_private = all_tournaments.filter(is_private=True).count()
        tournaments_all_public = all_tournaments.filter(is_private=False).count()
        tournaments_all_total = all_tournaments.count()

        # Ended tournaments (tournaments that have an end_date in the past)
        tournaments_ended_today = Tournament.objects.filter(
            end_date__date=today
        ).exclude(is_deleted=True)

        tournaments_ended_week = Tournament.objects.filter(
            end_date__date__gte=week_start,
            end_date__date__lte=week_end
        ).exclude(is_deleted=True)

        tournaments_ended_month = Tournament.objects.filter(
            end_date__date__gte=month_start,
            end_date__date__lte=today + timedelta(days=31 - today.day)
        ).exclude(is_deleted=True)

        tournaments_ended_all = Tournament.objects.filter(
            end_date__date__lt=today
        ).exclude(is_deleted=True)

        # Team and player statistics
        total_teams = TeamRegistration.objects.count()
        total_players = PlayerRegistration.objects.count()

        # Match statistics
        total_matches = Match.objects.count()
        matches_played = Match.objects.filter(end_date__isnull=False).count()
        matches_pending = Match.objects.filter(end_date__isnull=True).count()

        # Additional statistics
        tournaments_with_online_reg = Tournament.objects.filter(
            enable_online_registration=True
        ).exclude(is_deleted=True).count()

        tournaments_with_payment = Tournament.objects.filter(
            enable_online_payment=True
        ).exclude(is_deleted=True).count()

        # Average statistics
        avg_teams_per_tournament = TeamRegistration.objects.aggregate(
            avg_teams=Avg('tournament__team_count')
        )['avg_teams'] or 0

        avg_entry_fee = Tournament.objects.exclude(is_deleted=True).aggregate(
            avg_fee=Avg('entry_fee')
        )['avg_fee'] or 0

        # User Account Statistics
        total_users = CustomUser.objects.count()
        users_admin = CustomUser.objects.filter(origin=0).count()  # ADMIN
        users_site = CustomUser.objects.filter(origin=1).count()   # SITE
        users_app = CustomUser.objects.filter(origin=2).count()    # APP

        # Recent User Registrations
        recent_app_users = CustomUser.objects.filter(origin=2).order_by('-date_joined')[:10]

        # New users by period
        users_today = CustomUser.objects.filter(date_joined__date=today).count()
        users_this_week = CustomUser.objects.filter(
            date_joined__date__gte=week_start,
            date_joined__date__lte=week_end
        ).count()
        users_this_month = CustomUser.objects.filter(
            date_joined__date__gte=month_start,
            date_joined__date__lte=today + timedelta(days=31 - today.day)
        ).count()

        # Purchase Statistics
        total_purchases = Purchase.objects.count()
        recent_purchases = Purchase.objects.all().order_by('-purchase_date')[:10]

        # Purchases by period
        purchases_today = Purchase.objects.filter(purchase_date__date=today).count()
        purchases_this_week = Purchase.objects.filter(
            purchase_date__date__gte=week_start,
            purchase_date__date__lte=week_end
        ).count()
        purchases_this_month = Purchase.objects.filter(
            purchase_date__date__gte=month_start,
            purchase_date__date__lte=today + timedelta(days=31 - today.day)
        ).count()

        context = {
            'title': 'Tournament Dashboard',
            'app_label': 'tournaments',
            'opts': Tournament._meta,

            # Today statistics (tournaments STARTING today)
            'tournaments_today_total': tournaments_today_total,
            'tournaments_today_private': tournaments_today_private,
            'tournaments_today_public': tournaments_today_public,

            # Week statistics (tournaments STARTING this week)
            'tournaments_week_total': tournaments_week_total,
            'tournaments_week_private': tournaments_week_private,
            'tournaments_week_public': tournaments_week_public,

            # Month statistics (tournaments STARTING this month)
            'tournaments_month_total': tournaments_month_total,
            'tournaments_month_private': tournaments_month_private,
            'tournaments_month_public': tournaments_month_public,

            # All time statistics
            'tournaments_all_total': tournaments_all_total,
            'tournaments_all_private': tournaments_all_private,
            'tournaments_all_public': tournaments_all_public,

            # Ended tournaments (tournaments ENDING in the respective periods)
            'tournaments_ended_today': tournaments_ended_today.count(),
            'tournaments_ended_week': tournaments_ended_week.count(),
            'tournaments_ended_month': tournaments_ended_month.count(),
            'tournaments_ended_all': tournaments_ended_all.count(),

            # Teams and players
            'total_teams': total_teams,
            'total_players': total_players,

            # Matches
            'total_matches': total_matches,
            'matches_played': matches_played,
            'matches_pending': matches_pending,

            # Additional stats
            'tournaments_with_online_reg': tournaments_with_online_reg,
            'tournaments_with_payment': tournaments_with_payment,
            'avg_teams_per_tournament': round(avg_teams_per_tournament, 1),
            'avg_entry_fee': round(avg_entry_fee, 2),

            # User statistics
            'total_users': total_users,
            'users_admin': users_admin,
            'users_site': users_site,
            'users_app': users_app,
            'users_today': users_today,
            'users_this_week': users_this_week,
            'users_this_month': users_this_month,
            'recent_app_users': recent_app_users,

            # Purchase statistics
            'total_purchases': total_purchases,
            'recent_purchases': recent_purchases,
            'purchases_today': purchases_today,
            'purchases_this_week': purchases_this_week,
            'purchases_this_month': purchases_this_month,
        }

        return render(request, 'admin/tournaments/dashboard.html', context)

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('dashboard/', self.admin_site.admin_view(self.dashboard_view), name='tournaments_tournament_dashboard'),
        ]
        return custom_urls + urls

class TeamRegistrationAdmin(SyncedObjectAdmin):
    list_display = ['player_names', 'group_stage', 'name', 'tournament', 'registration_date']
    list_filter = [SimpleTournamentListFilter]
    search_fields = ['id']

class TeamScoreAdmin(SyncedObjectAdmin):
    list_display = ['team_registration', 'score', 'walk_out', 'match']
    list_filter = [TeamScoreTournamentListFilter]
    search_fields = ['id', 'team_registration__player_registrations__first_name', 'team_registration__player_registrations__last_name']
    raw_id_fields = ['team_registration', 'match']  # Add this line
    list_per_page = 50  # Controls pagination on the list view

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('team_registration', 'match')

class RoundAdmin(SyncedObjectAdmin):
    list_display = ['tournament', 'name', 'parent', 'index']
    list_filter = [SimpleTournamentListFilter, SimpleIndexListFilter]
    search_fields = ['id']
    ordering = ['parent', 'index']
    raw_id_fields = ['parent']  # Add this line
    list_per_page = 50  # Controls pagination on the list view

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('parent')

class PlayerRegistrationAdmin(SyncedObjectAdmin):
    list_display = ['first_name', 'last_name', 'licence_id', 'rank']
    search_fields = ['id', 'first_name', 'last_name', 'licence_id__icontains']
    list_filter = ['registered_online', 'payment_id', TeamScoreTournamentListFilter]
    ordering = ['last_name', 'first_name']
    raw_id_fields = ['team_registration']  # Add this line
    list_per_page = 50  # Controls pagination on the list view

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('team_registration')

class MatchAdmin(SyncedObjectAdmin):
    list_display = ['__str__', 'round', 'group_stage', 'start_date', 'end_date', 'index']
    list_filter = [MatchTypeListFilter, MatchTournamentListFilter, SimpleIndexListFilter]
    ordering = ['-group_stage', 'round', 'index']
    raw_id_fields = ['round', 'group_stage']  # Add this line
    list_per_page = 50  # Controls pagination on the list view

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('round', 'group_stage')

class GroupStageAdmin(SyncedObjectAdmin):
    list_display = ['tournament', 'start_date', 'index']
    list_filter = [SimpleTournamentListFilter]
    ordering = ['-start_date', 'index']

class ClubAdmin(SyncedObjectAdmin):
    list_display = ['name', 'acronym', 'city', 'creator', 'events_count', 'broadcast_code']
    search_fields = ['name', 'acronym', 'city']
    ordering = ['creator']
    raw_id_fields = ['creator', 'related_user']

class PurchaseAdmin(SyncedObjectAdmin):
    list_display = ['id', 'user', 'product_id', 'quantity', 'purchase_date', 'revocation_date', 'expiration_date']
    list_filter = ['user']
    ordering = ['-purchase_date']

class CourtAdmin(SyncedObjectAdmin):
    list_display = ['index', 'name', 'club']
    ordering = ['club']

class DateIntervalAdmin(SyncedObjectAdmin):
    list_display = ['court_index', 'event']

class FailedApiCallAdmin(admin.ModelAdmin):
    list_display = ['date', 'user', 'type', 'error']
    list_filter = ['user']

class LogAdmin(admin.ModelAdmin):
    list_display = ['date', 'user', 'message']
    list_filter = ['user']

class DeviceTokenAdmin(admin.ModelAdmin):
    list_display = ['user', 'value']
    list_filter = ['user']

class DrawLogAdmin(SyncedObjectAdmin):
    list_display = ['tournament', 'draw_date', 'draw_seed', 'draw_match_index', 'draw_team_position']
    list_filter = [SimpleTournamentListFilter]
    ordering = ['draw_date']

class UnregisteredTeamAdmin(admin.ModelAdmin):
    list_display = ['player_names', 'tournament']
    list_filter = [SimpleTournamentListFilter]

class UnregisteredPlayerAdmin(admin.ModelAdmin):
    list_display = ['first_name', 'last_name', 'licence_id']
    search_fields = ['first_name', 'last_name']
    list_filter = []
    ordering = ['last_name', 'first_name']

class ImageAdmin(admin.ModelAdmin):
    list_display = ['title', 'event', 'image_type', 'order', 'uploaded_at', 'file_size', 'image_preview_small']
    list_filter = ['event', 'image_type', 'uploaded_at']
    search_fields = ['title', 'description', 'event__name']
    ordering = ['order']
    readonly_fields = ['id', 'uploaded_at', 'image_preview', 'file_size']
    raw_id_fields = ['event']

    def image_preview(self, obj):
        if obj.image:
            return mark_safe(f'<img src="{obj.image.url}" width="150" height="auto" style="max-height: 150px; object-fit: contain;" />')
        return "No Image"
    image_preview.short_description = 'Preview'

    def image_preview_small(self, obj):
        if obj.image:
            return mark_safe(f'<img src="{obj.image.url}" width="50" height="auto" style="max-height: 50px; object-fit: contain;" />')
        return "No Image"
    image_preview_small.short_description = 'Preview'

    def file_size(self, obj):
        if obj.image and hasattr(obj.image, 'size'):
            # Convert bytes to KB or MB
            size_bytes = obj.image.size
            if size_bytes < 1024:
                return f"{size_bytes} bytes"
            elif size_bytes < 1024 * 1024:
                return f"{size_bytes/1024:.1f} KB"
            else:
                return f"{size_bytes/(1024*1024):.1f} MB"
        return "Unknown"
    file_size.short_description = 'File Size'


action_flags = {
    ADDITION: 'Addition',
    CHANGE: 'Change',
    DELETION: 'Deletion',
}

@admin.register(LogEntry)
class LogEntryAdmin(admin.ModelAdmin):
    date_hierarchy = 'action_time'
    list_filter = ['user', 'content_type', 'action_flag']
    search_fields = ['object_repr', 'change_message']
    list_display = ['action_time', 'user', 'content_type', 'object_link', 'action_flag_display', 'change_message']
    readonly_fields = [field.name for field in LogEntry._meta.get_fields()]

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

    def object_link(self, obj):
        if obj.action_flag == DELETION:
            link = escape(obj.object_repr)
        else:
            ct = obj.content_type
            try:
                link = '<a href="%s">%s</a>' % (
                    reverse('admin:%s_%s_change' % (ct.app_label, ct.model),
                            args=[obj.object_id]),
                    escape(obj.object_repr),
                )
            except:
                link = escape(obj.object_repr)
        return mark_safe(link)
    object_link.short_description = 'Object'

    def action_flag_display(self, obj):
        return action_flags.get(obj.action_flag, '')
    action_flag_display.short_description = 'Action'

admin.site.register(CustomUser, CustomUserAdmin)
admin.site.register(Club, ClubAdmin)
admin.site.register(Event, EventAdmin)
admin.site.register(Round, RoundAdmin)
admin.site.register(GroupStage, GroupStageAdmin)
admin.site.register(Match, MatchAdmin)
admin.site.register(TeamScore, TeamScoreAdmin)
admin.site.register(TeamRegistration, TeamRegistrationAdmin)
admin.site.register(Tournament, TournamentAdmin)
admin.site.register(PlayerRegistration, PlayerRegistrationAdmin)
admin.site.register(Purchase, PurchaseAdmin)
admin.site.register(Court, CourtAdmin)
admin.site.register(DateInterval, DateIntervalAdmin)
admin.site.register(FailedApiCall, FailedApiCallAdmin)
admin.site.register(Log, LogAdmin)
admin.site.register(DeviceToken, DeviceTokenAdmin)
admin.site.register(DrawLog, DrawLogAdmin)
admin.site.register(UnregisteredTeam, UnregisteredTeamAdmin)
admin.site.register(UnregisteredPlayer, UnregisteredPlayerAdmin)
admin.site.register(Image, ImageAdmin)
