import { Injectable, NotFoundException } from '@nestjs/common';
import { I18nService } from '../i18n/i18n.service';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { SearchHistory } from './search-history.entity';
import { ChatMessage } from './chat-message.entity';

export interface SearchHistoryItem {
  id: string;
  title: string;
  selectedGroups: string[] | null;
  messageCount: number;
  lastMessageAt: string;
  createdAt: string;
}

export interface SearchHistoryDetail {
  id: string;
  title: string;
  selectedGroups: string[] | null;
  messages: Array<{
    id: string;
    role: 'user' | 'assistant';
    content: string;
    sources?: any[];
    createdAt: string;
  }>;
}

export interface PaginatedSearchHistory {
  histories: SearchHistoryItem[];
  total: number;
  page: number;
  limit: number;
}

@Injectable()
export class SearchHistoryService {
  constructor(
    @InjectRepository(SearchHistory)
    private searchHistoryRepository: Repository<SearchHistory>,
    @InjectRepository(ChatMessage)
    private chatMessageRepository: Repository<ChatMessage>,
    private i18nService: I18nService,
  ) { }

  async findAll(
    userId: string,
    tenantId: string,
    page: number = 1,
    limit: number = 20,
  ): Promise<PaginatedSearchHistory> {
    const [histories, total] = await this.searchHistoryRepository.findAndCount({
      where: { userId, tenantId },
      order: { updatedAt: 'DESC' },
      skip: (page - 1) * limit,
      take: limit,
    });

    const items: SearchHistoryItem[] = await Promise.all(
      histories.map(async (history) => {
        const messageCount = await this.chatMessageRepository.count({
          where: { searchHistoryId: history.id },
        });

        const lastMessage = await this.chatMessageRepository.findOne({
          where: { searchHistoryId: history.id },
          order: { createdAt: 'DESC' },
        });

        return {
          id: history.id,
          title: history.title,
          selectedGroups: history.selectedGroups ? JSON.parse(history.selectedGroups) : null,
          messageCount,
          lastMessageAt: lastMessage?.createdAt.toISOString() || history.createdAt.toISOString(),
          createdAt: history.createdAt.toISOString(),
        };
      }),
    );

    return {
      histories: items,
      total,
      page,
      limit,
    };
  }

  async findOne(id: string, userId: string, tenantId?: string): Promise<SearchHistoryDetail> {
    const whereClause: any = { id, userId };
    if (tenantId) {
      whereClause.tenantId = tenantId;
    }
    const history = await this.searchHistoryRepository.findOne({
      where: whereClause,
      relations: ['messages'],
      order: { messages: { createdAt: 'ASC' } },
    });

    if (!history) {
      throw new NotFoundException(this.i18nService.getMessage('conversationHistoryNotFound'));
    }

    return {
      id: history.id,
      title: history.title,
      selectedGroups: history.selectedGroups ? JSON.parse(history.selectedGroups) : null,
      messages: history.messages.map((message) => ({
        id: message.id,
        role: message.role,
        content: message.content,
        sources: message.sources ? JSON.parse(message.sources) : undefined,
        createdAt: message.createdAt.toISOString(),
      })),
    };
  }

  async create(
    userId: string,
    tenantId: string,
    title: string,
    selectedGroups?: string[],
  ): Promise<SearchHistory> {
    const history = this.searchHistoryRepository.create({
      userId,
      tenantId,
      title: title.length > 50 ? title.substring(0, 50) + '...' : title,
      selectedGroups: selectedGroups ? JSON.stringify(selectedGroups) : undefined,
    });

    return await this.searchHistoryRepository.save(history);
  }

  async addMessage(
    historyId: string,
    role: 'user' | 'assistant',
    content: string,
    sources?: any[],
  ): Promise<ChatMessage> {
    const message = this.chatMessageRepository.create({
      searchHistoryId: historyId,
      role,
      content,
      sources: sources ? JSON.stringify(sources) : undefined,
    });

    const savedMessage = await this.chatMessageRepository.save(message);

    // Update history record update time
    await this.searchHistoryRepository.update(historyId, {
      updatedAt: new Date(),
    });

    return savedMessage;
  }

  async remove(id: string, userId: string, tenantId: string): Promise<void> {
    const history = await this.searchHistoryRepository.findOne({
      where: { id, userId, tenantId },
    });

    if (!history) {
      throw new NotFoundException(this.i18nService.getMessage('conversationHistoryNotFound'));
    }

    await this.searchHistoryRepository.remove(history);
  }

  async updateTitle(id: string, title: string, tenantId?: string): Promise<void> {
    const whereClause: any = { id };
    if (tenantId) {
      whereClause.tenantId = tenantId;
    }
    await this.searchHistoryRepository.update(whereClause, { title });
  }
}