import email
from django.contrib import admin
from django.shortcuts import render,redirect
from leaflet.admin import LeafletGeoAdmin
from leaflet.admin import LeafletGeoAdminMixin
from leaflet_admin_list.admin import LeafletAdminListMixin
from .models import RogUser, Location, Location2025, SystemSettings, JoinedEvent, Favorite, TravelList, TravelPoint, ShapeLayers, Event, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, CustomUser, GifuAreas, UserTracks, templocation, UserUpload, EventUser, GoalImages, CheckinImages, NewEvent2, Team, NewCategory, Entry, Member, TempUser, GifurogeRegister, GpsLog, GpsCheckin, Checkpoint, Waypoint
from django.contrib.auth.admin import UserAdmin
from django.urls import path,reverse
from django.shortcuts import render
from django import forms;
import requests

from django.http import HttpResponseRedirect
from django.utils.html import format_html
from .forms import CSVUploadForm
from .views import process_csv_upload

from django.db.models import F  # F式をインポート
from django.db import transaction
from django.contrib import messages
import csv
from io import StringIO,TextIOWrapper
from datetime import timedelta 
from django.contrib.auth.hashers import make_password
from datetime import datetime, date
from django.core.exceptions import ValidationError

from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import gettext_lazy as _

from .services.csv_processor import EntryCSVProcessor

@admin.register(Entry)
class EntryAdmin(admin.ModelAdmin):
    list_display = ['team', 'zekken_number', 'event', 'category', 'date', 'is_active']
    
    # change_list_templateの追加
    change_list_template = 'admin/entry/change_list.html'  # この行を追加
       
    def get_urls(self):
        from django.urls import path
        urls = super().get_urls()
        custom_urls = [
            path('upload-csv/', self.upload_csv_view, name='entry_upload_csv'),
        ]
        return custom_urls + urls

    def upload_csv_view(self, request):
        processor = EntryCSVProcessor()
        return processor.process_upload(request)

@admin.register(GifurogeRegister)
class GifurogeRegisterAdmin(admin.ModelAdmin):
    list_display = ('event_code', 'time', 'owner_name', 'email', 'team_name', 'department')
    change_list_template = 'admin/rog/gifurogeregister/change_list.html'  # この行を追加

    def find_matching_category(self, time, department):
        """
        時間とdepartmentに基づいて適切なカテゴリを見つける
        """
        try:
            duration = timedelta(hours=time)

            # 検索前の情報出力
            print(f"    Searching for category with parameters:")
            print(f"    - Duration: {duration}")
            print(f"    - Department: {department}")

            # 利用可能なカテゴリの一覧を出力
            all_categories = NewCategory.objects.all()
            print("    Available categories:")
            for cat in all_categories:
                #print(f"        - ID: {cat.id}")
                print(f"        - Name: {cat.category_name}")
                print(f"        - Duration: {cat.duration}")
                print(f"        - Number: {cat.category_number}")

            # カテゴリ検索のクエリをログ出力
            query = NewCategory.objects.filter(
                duration=duration,
                category_name__startswith=department
            )
            print(f"    Query SQL: {query.query}")

            # 検索結果の取得
            category = query.first()

            if category:
                print(f"    Found matching category:")
                print(f"    - Name: {category.category_name}")
                print(f"    - Duration: {category.duration}")
                print(f"    - Category Number: {getattr(category, 'category_number', 'N/A')}")

            else:
                print("    No matching category found with the following filters:")
                print(f"    - Duration equals: {duration}")
                print(f"    - Category name starts with: {department}")

            return category

        except Exception as e:
            print(f"Error finding category: {e}")
            print(f"Exception type: {type(e)}")
            import traceback
            print(f"Traceback: {traceback.format_exc()}")
            return None

    def create_entry_with_number(self, team, category, owner, event):
        """
        カテゴリ番号をインクリメントしてエントリーを作成
        """
        try:
            with transaction.atomic():
                # 事前バリデーション
                try:
                    # チームメンバーの性別をチェック
                    if category.female:
                        for member in team.members.all():

                            print(f"  Check existing member {member.user.lastname} {member.user.firstname} female:{member.user.female}")
                            if not member.user.female:
                                raise ValidationError(f"チーム '{team.team_name}' に男性メンバーが含まれているため、"
                                                   f"カテゴリー '{category.category_name}' には参加できません。")
                except ValidationError as e:
                    print(f"Pre-validation error: {str(e)}")
                    raise

                # カテゴリを再度ロックして取得
                category_for_update = NewCategory.objects.select_for_update().get(
                    category_name=category.category_name
                )

                print(f"    Creating entry with following details:")
                print(f"    - Category: {category_for_update.category_name}")
                print(f"    - Current category number: {category_for_update.category_number}")

                # イベントの日付を取得
                entry_date = event.start_datetime.date()
                
                # 既存のエントリーをチェック
                existing_entry = Entry.objects.filter(
                    team=team,
                    event=event,
                    date=entry_date,
                    is_active=True  # アクティブなエントリーのみをチェック
                ).first()
    
                if existing_entry:
                    print(f"    Found existing entry for team {team.team_name} on {entry_date}")
                    raise ValidationError(
                        f"Team {team.team_name} already has an entry for event {event.event_name} on {entry_date}"
                    )

                # 現在の番号を取得してインクリメント
                current_number = category_for_update.category_number
                zekken_number = current_number
                
                # カテゴリ番号をインクリメント
                category_for_update.category_number = F('category_number') + 1
                category_for_update.save()
  
                # 変更後の値を取得して表示
                category_for_update.refresh_from_db()
                print(f"    Updated category number: {category_for_update.category_number}")
  
                # エントリーの作成
                try:
                    entry = Entry.objects.create(
                        date=event.start_datetime,
                        team=team,
                        category=category,
                        owner=owner,
                        event=event,
                        zekken_number=zekken_number,
                        is_active=True
                    )
                    # バリデーションを実行
                    entry.full_clean()
                    # 問題なければ保存
                    entry.save()
    
                    print(f"    Created entry:")
                    print(f"    - Team: {team.team_name}")
                    print(f"    - Event: {event.event_name}")
                    print(f"    - Category: {category.category_name}")
                    print(f"    - Zekken Number: {zekken_number}")
    
                    return entry

                except ValidationError as e:
                    print(f"Entry validation error: {str(e)}")
                    raise
                
        except Exception as e:
            print(f"Error creating entry: {e}")
            print(f"Exception type: {type(e)}")
            import traceback
            print(f"Traceback: {traceback.format_exc()}")
            raise

    def split_full_name(self, full_name):
        """
        フルネームを姓と名に分割
        半角または全角スペースに対応
        """
        try:
            # 空白文字で分割（半角スペース、全角スペース、タブなど）
            parts = full_name.replace('　', ' ').split()
            if len(parts) >= 2:
                last_name = parts[0]
                first_name = ' '.join(parts[1:])  # 名が複数単語の場合に対応
                return last_name, first_name
            else:
                # 分割できない場合は全体を姓とする
                return full_name, ''
        except Exception as e:
            print(f"Error splitting name '{full_name}': {e}")
            return full_name, ''

    def convert_japanese_date(self, date_text):
        """
        日本式の日付テキストをDateField形式に変換
        例: '1990年1月1日' -> datetime.date(1990, 1, 1)
        """
        try:
            if not date_text or date_text.strip() == '':
                return None
    
            # 全角数字を半角数字に変換
            date_text = date_text.translate(str.maketrans('０１２３４５６７８９', '0123456789'))
            date_text = date_text.strip()

            # 区切り文字の判定と分割
            if '年' in date_text:
                # 年月日形式の場合
                date_parts = date_text.replace('年', '-').replace('月', '-').replace('日', '').split('-')
            elif '/' in date_text:
                # スラッシュ区切りの場合
                date_parts = date_text.split('/')
            elif '-' in date_text:
                date_parts = date_text.split('-')
            else:
                print(f"Unsupported date format: {date_text}")
                return None
    
            # 部分の数を確認
            if len(date_parts) != 3:
                print(f"Invalid date parts count: {len(date_parts)} in '{date_text}'")
                return None
    
            year = int(date_parts[0])
            month = int(date_parts[1])
            day = int(date_parts[2])
            
            # 簡単な妥当性チェック
            if not (1900 <= year <= 2100):
                print(f"Invalid year: {year}")
                return None
            if not (1 <= month <= 12):
                print(f"Invalid month: {month}")
                return None
            if not (1 <= day <= 31):  # 月ごとの日数チェックは省略
                print(f"Invalid day: {day}")
                return None

            print(f"Converted from {date_text} to year-{year} / month-{month} / day-{day}")

            return date(year, month, day)
            
        except Exception as e:
            print(f"Error converting date '{date_text}': {str(e)}")
            return None

    def create_owner_member( self,team,row ):
        """
        オーナーをチームメンバー１として作成
        既存のメンバーは更新
        """
        try:
            owner_name = row.get('owner_name').strip()
            # 姓名を分割
            last_name, first_name = self.split_full_name(owner_name)
            print(f"    Split name - Last: {last_name}, First: {first_name}")
            # 誕生日の処理
            birthday = row.get(f'owner_birthday', '').strip()
            birth_date = self.convert_japanese_date(birthday)
            print(f"    Converted birthday: {birth_date}")
 
            # 性別の処理
            sex = row.get(f'owner_sex', '').strip()
            is_female = sex in ['女性','女','女子','female','girl','lady']
            print(f"    Sex: {sex}, is_female: {is_female}")

            # メンバーを作成
            member,created = Member.objects.get_or_create(
                team=team,
                user=team.owner,
                defaults={
                    'is_temporary': True   # 仮登録
                }
            )


            # 既存メンバーの場合は情報を更新
            if not created:
                member.lastname = last_name
                member.firstname = first_name
                member.date_of_birth = birth_date
                member.female = is_female
                member.is_temporary = True
                member.save()
                print(f"    Updated existing member {last_name} {first_name}")
            else:
                print(f"    Created new member {last_name} {first_name}")

            return member

        except Exception as e:
            print(f"Error creating/updating member: {e}")
            raise

    def create_members(self, team, row):
        """
        チームのメンバーを作成
        既存のメンバーは更新
        """
        try:
            created_members = []

            # オーナーをメンバーに登録
            member = self.create_owner_member(team,row)
            created_members.append(member)

            # メンバー2から5までを処理
            for i in range(2, 6):
                member_name = row.get(f'member{i}', '').strip()
                if member_name:
                    print(f"=====  Processing member: {member_name} =====")

                    # 姓名を分割
                    last_name, first_name = self.split_full_name(member_name)
                    print(f"    Split name - Last: {last_name}, First: {first_name}")

                    # 誕生日の処理
                    birthday = row.get(f'birthday{i}', '').strip()
                    birth_date = self.convert_japanese_date(birthday)
                    print(f"    Converted birthday: {birth_date}")
    
                    # 性別の処理
                    sex = row.get(f'sex{i}', '').strip()
                    is_female = sex in ['女性','女','女子','female','girl','lady']
                    print(f"    Sex: {sex}, is_female: {is_female}")

                    # メンバー用のユーザーを作成
                    email = f"dummy_{team.id}_{i}@gifuai.net".lower()
                    member_user, created = CustomUser.objects.get_or_create(
                        email=email,
                        defaults={
                            'password': make_password('temporary_password'),
                            'lastname': last_name,
                            'firstname': first_name,
                            'date_of_birth': birth_date,
                            'female':is_female
                        }
                    )

                    # 既存ユーザーの場合も姓名を更新
                    if not created:
                        member_user.lastname = last_name
                        member_user.firstname = first_name
                        member_user.date_of_birth = birth_date
                        member_user.female = is_female
                        member_user.save()

                    try:
                            # メンバーを作成
                        member,created = Member.objects.get_or_create(
                            team=team,
                            user=member_user,
                            defaults={
                                'is_temporary': True   # 仮登録
                            }
                        )
    
                        # 既存メンバーの場合は情報を更新
                        if not created:
                            member.is_temporary = True
                            member.save()
                            print(f"    Updated existing member {member_user.lastname} {member_user.firstname}")
                        else:
                            print(f"    Created new member {member_user.lastname} {member_user.firstname}")
    
                        created_members.append(member)
                        print(f"    - Birthday: {member_user.date_of_birth}")
                        print(f"    - Sex: {'Female' if member_user.female else 'Male'}")
    
                    except Exception as e:
                        print(f"Error creating/updating member: {e}")
                        raise

            return created_members

        except Exception as e:
            print(f"Error creating members: {e}")
            print(f"Exception type: {type(e)}")
            import traceback
            print(f"Traceback: {traceback.format_exc()}")
            raise

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('upload-csv/', self.upload_csv, name='gifuroge_register_upload_csv'),
        ]
        return custom_urls + urls

    def upload_csv(self, request):
        print("upload_csv")
        if request.method == 'POST':
            print("POST")
            if 'csv_file' not in request.FILES:
                messages.error(request, 'No file was uploaded.')
                return redirect('..')
            
            csv_file = request.FILES['csv_file']
            print(f"csv_file(1) = {csv_file}")
            if not csv_file.name.endswith('.csv'):
                messages.error(request, 'File is not CSV type')
                return redirect('..')

            try:
                # BOMを考慮してファイルを読み込む
                file_content = csv_file.read()
                # BOMがある場合は除去
                if file_content.startswith(b'\xef\xbb\xbf'):
                    file_content = file_content[3:]

                # デコード
                file_content = file_content.decode('utf-8')
                csv_file = StringIO(file_content)
                reader = csv.DictReader(csv_file)

                print(f"csv_file(2) = {csv_file}")
                print(f"reader = {reader}")

                with transaction.atomic():
                    for row in reader:
                        print(f"    row={row}")

                        # オーナーの姓名を分割
                        owner_lastname, owner_firstname = self.split_full_name(row['owner_name'])

                        # パスワードをハッシュ化
                        hashed_password = make_password(row['password'])

                        # オーナーの誕生日の処理
                        owner_birthday = row.get('owner_birthday', '').strip()
                        owner_birth_date = self.convert_japanese_date(owner_birthday)
                        print(f"    Owner birthday: {owner_birth_date}")
                
                        # オーナーの性別の処理
                        owner_sex = row.get('owner_sex', '').strip()
                        owner_is_female = owner_sex in ['女性','女','女子','female','girl','lady']
                        print(f"    Owner sex: {owner_sex}, is_female: {owner_is_female}")

                        # ユーザーの取得または作成
                        user, created = CustomUser.objects.get_or_create(
                            email=row['email'],
                            defaults={
                                'password': hashed_password,  # make_password(row['password'])
                                'lastname': owner_lastname,
                                'firstname': owner_firstname,
                                'date_of_birth': owner_birth_date,
                                'female': owner_is_female
                            }
                        )

                        if not created:
                            # 既存ユーザーの場合、空のフィールドがあれば更新
                            should_update = False
                            update_fields = []
                        
                            print(f"    Checking existing user data for {user.email}:")
                            print(f"    - Current lastname: '{user.lastname}'")
                            print(f"    - Current firstname: '{user.firstname}'")
                            print(f"    - Current birth date: {user.date_of_birth}")
                            print(f"    - Current female: {user.female}")
                        
                            # 姓が空またはNoneの場合
                            if not user.lastname or user.lastname.strip() == '':
                                user.lastname = owner_lastname
                                should_update = True
                                update_fields.append('lastname')
                                print(f"    - Updating lastname to: {owner_lastname}")
                        
                            # 名が空またはNoneの場合
                            if not user.firstname or user.firstname.strip() == '':
                                user.firstname = owner_firstname
                                should_update = True
                                update_fields.append('firstname')
                                print(f"    - Updating firstname to: {owner_firstname}")
                        
                            # 生年月日が空またはNoneの場合
                            if not user.date_of_birth and owner_birth_date:
                                user.date_of_birth = owner_birth_date
                                should_update = True
                                update_fields.append('date_of_birth')
                                print(f"    - Updating birth date to: {owner_birth_date}")
                        
                            # 性別が空またはNoneの場合
                            # Booleanフィールドなのでis None で判定
                            if user.female is None:
                                user.female = owner_is_female
                                should_update = True
                                update_fields.append('female')
                                print(f"    - Updating female to: {owner_is_female}")
                        
                            # パスワードが'登録済み'でない場合のみ更新
                            if row['password'] != '登録済み':
                                user.password = hashed_password
                                should_update = True
                                update_fields.append('password')
                                print(f"    - Updating password")
                        
                            # 変更があった場合のみ保存
                            if should_update:
                                try:
                                    # 特定のフィールドのみを更新
                                    user.save(update_fields=update_fields)
                                    print(f"    Updated user {user.email} fields: {', '.join(update_fields)}")
                                except Exception as e:
                                    print(f"    Error updating user {user.email}: {str(e)}")
                                    raise
                            else:
                                print(f"    No updates needed for user {user.email}")


                        print(f"    user created...")
                        print(f"    Owner member created: {user.lastname} {user.firstname}")
                        print(f"    - Birthday: {user.date_of_birth}")
                        print(f"    - Sex: {'Female' if user.female else 'Male'}")

                        # 適切なカテゴリを見つける
                        category = self.find_matching_category(
                            time=int(row['time']),
                            department=row['department']
                        )

                        if not category:
                            raise ValueError(
                                f"No matching category found for time={row['time']} minutes "
                                f"and department={row['department']}"
                            )

                        print(f"    Using category: {category.category_name}")

                        # Teamの作成（既存のチームがある場合は取得）
                        team, created = Team.objects.get_or_create(
                            team_name=row['team_name'],
                            defaults={
                                'owner': user,
                                'category': category
                            }
                        )
                            
                        # 既存のチームの場合でもカテゴリを更新
                        if not created:
                            team.category = category
                            team.save()
                            
                        print("    team created/updated...")

                        self.create_members(team, row)

                        # イベントの検索
                        try:
                            event_code = row['event_code']
                            event = NewEvent2.objects.get(event_name=event_code)
                            print(f"    Found event: {event.event_name}")
                        except NewEvent2.DoesNotExist:
                            raise ValueError(f"Event with code {event_code} does not exist")

                        try:
                            # エントリーの作成
                            entry = self.create_entry_with_number(
                                team=team,
                                category=category,
                                owner=user,
                                event=event,
                            )

                            print("    entry created...")
                        except ValidationError as e:
                            messages.error(request, str(e))
                            return redirect('..')

                        gifuroge_register = GifurogeRegister.objects.create(
                            event_code=row['event_code'],
                            time=int(row['time']),
                            owner_name_kana=row['owner_name_kana'],
                            owner_name=row['owner_name'],
                            owner_birthday=self.convert_japanese_date(row['owner_birthday']),
                            owner_sex=row['owner_sex'],
                            email=row['email'],
                            password=row['password'],
                            team_name=row['team_name'],
                            department=row['department'],
                            members_count=int(row['members_count']),
                            member2=row.get('member2', '') or None,
                            birthday2=self.convert_japanese_date(row.get('birthday2', '') ),
                            sex2=row.get('sex2', '') or None,
                            member3=row.get('member3', '') or None,
                            birthday3=self.convert_japanese_date(row.get('birthday3', '') ),
                            sex3=row.get('sex3', '') or None,
                            member4=row.get('member4', '') or None,
                            birthday4=self.convert_japanese_date(row.get('birthday4', '') ),
                            sex4=row.get('sex4', '') or None,
                            member5=row.get('member5', '') or None,
                            birthday5=self.convert_japanese_date(row.get('birthday5', '') ),
                            sex5=row.get('sex5', '') or None
                        )
                        print(f"    saved gifuroge_register...")

            except UnicodeDecodeError:
                messages.error(request, 'File encoding error. Please ensure the file is UTF-8 encoded.')
                return redirect('..')
            except Exception as e:
                print(f"Error processing row: {e}")
                raise

            messages.success(request, 'CSV file uploaded successfully')
            return redirect('..')

        return render(request, 'admin/rog/gifurogeregister/upload-csv.html')

class RogAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
    list_display=['title', 'venue', 'at_date',]

class ShopAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
    list_display=['name',]

class EventRouteAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
    list_display=['name',]

class ShopRouteAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
    list_display=['name',]

class loadUserForm(forms.Form):
    server_url = forms.CharField(label="Load Data from *" ,initial='https://natnats.mobilous.com/get_team_list', widget=forms.Textarea(attrs={"rows":2, "cols":95}))


class UserAdminConfig(UserAdmin):
    search_fields = ('email', 'group', 'zekken_number', 'event_code', 'team_name', 'is_rogaining')
    list_filter = ('email', 'group', 'is_rogaining')
    ordering = ('email',)
    list_display = ('email', 'group','zekken_number', 'event_code', 'team_name', 'is_active', 'is_staff', 'is_rogaining')

    def get_urls(self):
        urls = super().get_urls()
        new_url = [path('load-users/', self.loadUsers),]
        return new_url + urls

    def loadUsers(self, request):

        if request.method == "POST":
            frm = loadUserForm(request.POST)
            if frm.is_valid():
                print(frm.cleaned_data['server_url'])
                #load json from server
                url = frm.cleaned_data['server_url']
                response = requests.get(url)
                data = response.json()
                print("-------Event code--------")
                print(data)
                print("-------Event code--------")
                for i in data:
                    _exist = CustomUser.objects.filter(email=i["zekken_number"]).delete()
                    other_fields.setDefaut('zekken_number',i['zekken_number'])
                    other_fields.setdefault('is_staff', True)
                    other_fields.setdefault('is_superuser', False)
                    other_fields.setdefault('is_active', True)
                    other_fields.setdefault('event_code', i['event_code'])
                    other_fields.setdefault('team_name', i['team_name'])
                    other_fields.setdefault('group', '大垣-初心者')

                    usr = CustomUser.objects.create_user(
                        email=i["zekken_number"],
                        password=i['password'],
                        **other_fields
                    )

        form = loadUserForm()
        data = {'form': form}
        return render(request, 'admin/load_users.html', data)

    """
    fieldsets = (
        (None, {'fields':('email', 'group', 'zekken_number', 'event_code', 'team_name',)}),
        ('Permissions', {'fields':('is_staff', 'is_active', 'is_rogaining')}),
    )

    add_fieldsets = (
        (None, {'classes':('wide',), 'fields':('email', 'group','zekken_number', 'event_code', 'team_name', 'password1', 'password2')}),
    )
    """
    # readonly_fieldsを明示的に設定
    readonly_fields = ('date_joined',)  # 変更不可のフィールドのみを指定=>Personal Infoも編集可能にする。

    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        (_('Personal info'), {
            'fields': ('firstname', 'lastname', 'date_of_birth', 'female'),
            'classes': ('wide',)  # フィールドの表示を広げる
            }),
        (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_rogaining','user_permissions')}),
        (_('Rogaining info'), {
            'fields': ('zekken_number', 'event_code', 'team_name', 'group'),
            'classes': ('wide',)
            }),
        (_('Important dates'), {
            'fields': ('date_joined','last_login'),
            'classes': ('wide',)
            }), # 読み取り専用
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            #'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active', 'is_rogaining')}
            'fields': ('email', 'password1', 'password2', 'lastname','firstname', 'date_of_birth', 'female','is_staff', 'is_active', 'is_rogaining')}
        ),
    )
    search_fields = ('email', 'firstname', 'lastname', 'zekken_number', 'team_name')
    ordering = ('email',)

class JpnSubPerfAdmin(LeafletGeoAdmin):
    search_fields = ('adm0_ja', 'adm1_ja', 'adm2_ja', 'name_modified', 'area_name',)
    list_filter = ('adm0_ja', 'adm0_ja', 'name_modified',)
    ordering = ('adm0_ja',)
    list_display = ('adm0_ja','adm1_ja','adm2_ja' ,'name_modified', 'area_name',)

class LocationAdmin(LeafletGeoAdmin):
    search_fields = ('location_id', 'cp', 'location_name', 'category', 'event_name','group',)
    list_filter = ('event_name', 'group',)
    ordering = ('location_id', 'cp',)
    list_display = ('location_id','sub_loc_id', 'cp', 'location_name', 'photos', 'category', 'group', 'event_name', 'event_active', 'auto_checkin', 'checkin_radius', 'checkin_point', 'buy_point',)


def tranfer_to_location(modeladmin, request, queryset):
    tmp_locs = templocation.objects.all();
    for l in tmp_locs :
        found = Location.objects.filter(location_id = l.location_id).exists()
        if found:
            Location.objects.filter(location_id = l.location_id).update(
            sub_loc_id = l.sub_loc_id,
            cp = l.cp,
            location_name = l.location_name,
            category = l.category,
            subcategory = l.subcategory,
            zip = l.zip,
            address = l.address,
            prefecture = l.prefecture,
            area = l.area,
            city = l.city,
            latitude = l.latitude,
            longitude = l.longitude,
            photos = l.photos,
            videos = l.videos,
            webcontents = l.webcontents,
            status = l.status,
            portal = l.portal,
            group = l.group,
            phone = l.phone,
            fax = l.fax,
            email = l.email,
            facility = l.facility,
            remark = l.remark,
            tags = l.tags,
            hidden_location = l.hidden_location,
            auto_checkin = l.auto_checkin,
            checkin_radius = l.checkin_radius,
            checkin_point = l.checkin_point,
            buy_point = l.buy_point,
            evaluation_value = l.evaluation_value,
            shop_closed = l.shop_closed,
            shop_shutdown = l.shop_shutdown,
            opening_hours_mon = l.opening_hours_mon,
            opening_hours_tue = l.opening_hours_tue,
            opening_hours_wed = l.opening_hours_wed,
            opening_hours_thu = l.opening_hours_thu,
            opening_hours_fri = l.opening_hours_fri,
            opening_hours_sat = l.opening_hours_sat,
            opening_hours_sun = l.opening_hours_sun,
            geom=l.geom
            )
        else:
            loc = Location(
                location_id=l.location_id,
                sub_loc_id = l.sub_loc_id,
                cp = l.cp,
                location_name = l.location_name,
                category = l.category,
                subcategory = l.subcategory,
                zip = l.zip,
                address = l.address,
                prefecture = l.prefecture,
                area = l.area,
                city = l.city,
                latitude = l.latitude,
                longitude = l.longitude,
                photos = l.photos,
                videos = l.videos,
                webcontents = l.webcontents,
                status = l.status,
                portal = l.portal,
                group = l.group,
                phone = l.phone,
                fax = l.fax,
                email = l.email,
                facility = l.facility,
                remark = l.remark,
                tags = l.tags,
                hidden_location = l.hidden_location,
                auto_checkin = l.auto_checkin,
                checkin_radius = l.checkin_radius,
                checkin_point = l.checkin_point,
                buy_point = l.buy_point,
                evaluation_value = l.evaluation_value,
                shop_closed = l.shop_closed,
                shop_shutdown = l.shop_shutdown,
                opening_hours_mon = l.opening_hours_mon,
                opening_hours_tue = l.opening_hours_tue,
                opening_hours_wed = l.opening_hours_wed,
                opening_hours_thu = l.opening_hours_thu,
                opening_hours_fri = l.opening_hours_fri,
                opening_hours_sat = l.opening_hours_sat,
                opening_hours_sun = l.opening_hours_sun,
                geom=l.geom
            )
            loc.save()
        l.delete()
    return True

#tranfer_to_location.short_description = "Transfer all locations in temp table to location table"


class TempLocationAdmin(LeafletGeoAdmin):
    search_fields = ('location_id', 'cp', 'location_name', 'category', 'event_name',)
    list_filter = ('category', 'event_name',)
    ordering = ('location_id', 'cp',)
    list_display = ('location_id','cp', 'location_name', 'category', 'event_name', 'event_active', 'auto_checkin', 'checkin_radius', 'checkin_point', 'buy_point',)
    actions = [tranfer_to_location,]

 
@admin.register(NewEvent2)
class NewEvent2Admin(admin.ModelAdmin):
    list_display = ['event_name', 'start_datetime', 'end_datetime', 'csv_upload_button']

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
                path('csv-upload/', self.admin_site.admin_view(self.csv_upload_view), name='newevent2_csv_upload'),
        ]
        return my_urls + urls

    def csv_upload_view(self, request):
        if request.method == 'POST':
            form = CSVUploadForm(request.POST, request.FILES)
            if form.is_valid():
                csv_file = request.FILES['csv_file']
                event = form.cleaned_data['event']
                process_csv_upload(csv_file, event)
                self.message_user(request, "CSV file has been processed successfully.")
                return HttpResponseRedirect("../")
        else:
            form = CSVUploadForm()

        return render(request, 'admin/csv_upload.html', {'form': form})

    def csv_upload_button(self, obj):
        url = reverse('admin:newevent2_csv_upload')
        return format_html('<a class="button" href="{}">CSVアップロード</a>', url)
    csv_upload_button.short_description = 'CSV Upload'

    def changelist_view(self, request, extra_context=None):
        extra_context = extra_context or {}
        extra_context['csv_upload_url'] = reverse('admin:newevent2_csv_upload')
        return super().changelist_view(request, extra_context=extra_context)


@admin.register(Team)
class TeamAdmin(admin.ModelAdmin):
    list_display = ['team_name', 'owner']
    search_fields = ['team_name', 'owner__email']

@admin.register(NewCategory)
class NewCategoryAdmin(admin.ModelAdmin):
    list_display = ['category_name', 'category_number', 'duration', 'num_of_member', 'family', 'female']
    list_filter = ['family', 'female']
    search_fields = ['category_name']

#@admin.register(Entry)
#class EntryAdmin(admin.ModelAdmin):
#    list_display = ['team', 'event', 'category', 'date']
#    list_filter = ['event', 'category']
#    search_fields = ['team__team_name', 'event__event_name']

@admin.register(Member)
class MemberAdmin(admin.ModelAdmin):
    list_display = ['team', 'user']
    search_fields = ['team__team_name', 'user__email']

@admin.register(TempUser)
class TempUserAdmin(admin.ModelAdmin):
    list_display = ['email', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'created_at', 'expires_at']
    list_filter = ['is_rogaining', 'group']
    search_fields = ['email', 'zekken_number', 'team_name']


# CustomUserAdmin の修正（既存のものを更新）
class CustomUserChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = CustomUser
        fields = '__all__'

class CustomUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = CustomUser
        fields = ('email', 'lastname', 'firstname', 'date_of_birth', 'female')

@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
    form = CustomUserChangeForm
    add_form = CustomUserCreationForm
    #model = CustomUser

    list_display = ('email', 'is_staff', 'is_active', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname')
    search_fields = ('egit mail', 'firstname', 'lastname', 'zekken_number')
    list_filter = ('is_staff', 'is_active', 'is_rogaining', 'group')
    ordering = ('email',)

    # readonly_fieldsを明示的に設定
    readonly_fields = ('date_joined',)  # 変更不可のフィールドのみを指定=>Personal Infoも編集可能にする。

    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        (_('Personal info'), {
            'fields': ('firstname', 'lastname', 'date_of_birth', 'female'),
            'classes': ('wide',)  # フィールドの表示を広げる
            }),
        (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_rogaining','user_permissions')}),
        (_('Rogaining info'), {
            'fields': ('zekken_number', 'event_code', 'team_name', 'group'),
            'classes': ('wide',)
            }),
        (_('Important dates'), {
            'fields': ('date_joined','last_login'),
            'classes': ('wide',)
            }), # 読み取り専用
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            #'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active', 'is_rogaining')}
            'fields': ('email', 'password1', 'password2', 'lastname','firstname', 'date_of_birth', 'female','is_staff', 'is_active', 'is_rogaining')}
        ),
    )
    search_fields = ('email', 'firstname', 'lastname', 'zekken_number', 'team_name')
    ordering = ('email',)

    def get_readonly_fields_old(self, request, obj=None):
        # スーパーユーザーの場合は読み取り専用フィールドを最小限に
        if request.user.is_superuser:
            return self.readonly_fields
        # 通常のスタッフユーザーの場合は追加の制限を設定可能
        return self.readonly_fields + ('is_staff', 'is_superuser')

    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser:
            return ('date_joined', 'last_login')
        return ('date_joined', 'last_login', 'is_staff', 'is_superuser')


admin.site.register(Useractions)
admin.site.register(RogUser, admin.ModelAdmin)
admin.site.register(Location, LocationAdmin) 
admin.site.register(SystemSettings, admin.ModelAdmin) 
admin.site.register(JoinedEvent, admin.ModelAdmin) 
admin.site.register(Favorite, admin.ModelAdmin) 
admin.site.register(TravelList, admin.ModelAdmin) 
admin.site.register(TravelPoint, admin.ModelAdmin)
admin.site.register(Event, admin.ModelAdmin)
admin.site.register(Location_line,  LeafletGeoAdmin)
admin.site.register(Location_polygon, LeafletGeoAdmin)
admin.site.register(JpnAdminMainPerf, LeafletGeoAdmin)
admin.site.register(UserTracks, LeafletGeoAdmin);
#admin.site.register(JpnAdminPerf, LeafletGeoAdmin)
admin.site.register(GifuAreas, LeafletGeoAdmin)
admin.site.register(ShapeLayers, admin.ModelAdmin)
admin.site.register(UserUpload, admin.ModelAdmin)
admin.site.register(EventUser, admin.ModelAdmin)
#admin.site.register(UserUploadUser, admin.ModelAdmin)
#admin.site.register(ShapeFileLocations, admin.ModelAdmin)

#admin.site.register(CustomUser, UserAdminConfig)
admin.site.register(templocation, TempLocationAdmin)
admin.site.register(GoalImages, admin.ModelAdmin)
admin.site.register(CheckinImages, admin.ModelAdmin)

# GpsLogとその他の新しいモデルの登録
@admin.register(GpsLog)
class GpsLogAdmin(admin.ModelAdmin):
    list_display = ['id', 'serial_number', 'zekken_number', 'event_code', 'cp_number', 'checkin_time']
    list_filter = ['event_code', 'checkin_time', 'buy_flag', 'is_service_checked']
    search_fields = ['zekken_number', 'event_code', 'cp_number']
    readonly_fields = ['checkin_time']

@admin.register(GpsCheckin)
class GpsCheckinAdmin(admin.ModelAdmin):
    list_display = ['id', 'zekken', 'event_code', 'cp_number', 'checkin_time']
    list_filter = ['event_code', 'checkin_time']
    search_fields = ['zekken', 'event_code', 'cp_number']
    readonly_fields = ['checkin_time', 'record_time']

@admin.register(Checkpoint)
class CheckpointAdmin(admin.ModelAdmin):
    list_display = ['id', 'cp_name', 'cp_number', 'photo_point', 'buy_point']
    search_fields = ['cp_name', 'cp_number']
    list_filter = ['photo_point', 'buy_point']
    readonly_fields = ['created_at', 'updated_at']

@admin.register(Waypoint)
class WaypointAdmin(admin.ModelAdmin):
    list_display = ['id', 'entry', 'latitude', 'longitude', 'recorded_at']
    search_fields = ['entry__team_name']
    list_filter = ['recorded_at']
    readonly_fields = ['created_at']


@admin.register(Location2025)
class Location2025Admin(LeafletGeoAdmin):
    """Location2025の管理画面"""
    list_display = [
        'cp_number', 'cp_name', 'event', 'total_point', 'is_active', 
        'csv_upload_date', 'created_at'
    ]
    list_filter = [
        'event', 'is_active', 'shop_closed', 'shop_shutdown', 
        'csv_upload_date', 'created_at'
    ]
    search_fields = ['cp_name', 'address', 'description']
    readonly_fields = [
        'csv_source_file', 'csv_upload_date', 'csv_upload_user',
        'created_at', 'updated_at', 'created_by', 'updated_by'
    ]
    
    fieldsets = (
        ('基本情報', {
            'fields': ('cp_number', 'event', 'cp_name', 'is_active', 'sort_order')
        }),
        ('位置情報', {
            'fields': ('latitude', 'longitude', 'location', 'address')
        }),
        ('ポイント設定', {
            'fields': ('cp_point', 'photo_point', 'buy_point')
        }),
        ('チェックイン設定', {
            'fields': ('checkin_radius', 'auto_checkin')
        }),
        ('営業情報', {
            'fields': ('shop_closed', 'shop_shutdown', 'opening_hours')
        }),
        ('詳細情報', {
            'fields': ('phone', 'website', 'description')
        }),
        ('CSV情報', {
            'fields': ('csv_source_file', 'csv_upload_date', 'csv_upload_user'),
            'classes': ('collapse',)
        }),
        ('管理情報', {
            'fields': ('created_at', 'updated_at', 'created_by', 'updated_by'),
            'classes': ('collapse',)
        }),
    )
    
    # CSV一括アップロード機能
    change_list_template = 'admin/location2025/change_list.html'
    
    def get_urls(self):
        from django.urls import path
        urls = super().get_urls()
        custom_urls = [
            path('upload-csv/', self.upload_csv_view, name='location2025_upload_csv'),
            path('export-csv/', self.export_csv_view, name='location2025_export_csv'),
        ]
        return custom_urls + urls
    
    def upload_csv_view(self, request):
        """CSVアップロード画面"""
        if request.method == 'POST':
            if 'csv_file' in request.FILES and 'event' in request.POST:
                csv_file = request.FILES['csv_file']
                event_id = request.POST['event']
                
                try:
                    from .models import NewEvent2
                    event = NewEvent2.objects.get(id=event_id)
                    
                    # CSVインポート実行
                    result = Location2025.import_from_csv(
                        csv_file, 
                        event, 
                        user=request.user
                    )
                    
                    # 結果メッセージ
                    if result['errors']:
                        messages.warning(
                            request, 
                            f"インポート完了: 作成{result['created']}件, 更新{result['updated']}件, "
                            f"エラー{len(result['errors'])}件 - {'; '.join(result['errors'][:5])}"
                        )
                    else:
                        messages.success(
                            request,
                            f"CSVインポートが完了しました。作成: {result['created']}件, 更新: {result['updated']}件"
                        )
                    
                except Exception as e:
                    messages.error(request, f"CSVインポートエラー: {str(e)}")
                
                return redirect('..')
        
        # フォーム表示
        from .models import NewEvent2
        events = NewEvent2.objects.filter(event_active=True).order_by('-created_at')
        
        return render(request, 'admin/location2025/upload_csv.html', {
            'events': events,
            'title': 'チェックポイントCSVアップロード'
        })
    
    def export_csv_view(self, request):
        """CSVエクスポート"""
        import csv
        from django.http import HttpResponse
        from django.utils import timezone
        
        response = HttpResponse(content_type='text/csv; charset=utf-8')
        response['Content-Disposition'] = f'attachment; filename="checkpoints_{timezone.now().strftime("%Y%m%d_%H%M%S")}.csv"'
        
        # BOM付きUTF-8で出力
        response.write('\ufeff')
        
        writer = csv.writer(response)
        writer.writerow([
            'cp_number', 'cp_name', 'latitude', 'longitude', 'cp_point', 
            'photo_point', 'buy_point', 'address', 'phone', 'description'
        ])
        
        queryset = self.get_queryset(request)
        for obj in queryset:
            writer.writerow([
                obj.cp_number, obj.cp_name, obj.latitude, obj.longitude,
                obj.cp_point, obj.photo_point, obj.buy_point,
                obj.address, obj.phone, obj.description
            ])
        
        return response
    
    def save_model(self, request, obj, form, change):
        """保存時にユーザー情報を自動設定"""
        if not change:  # 新規作成時
            obj.created_by = request.user
        obj.updated_by = request.user
        super().save_model(request, obj, form, change)