# .github/workflows/translate.yml

name: Translate New and Specific JA Content

on:
  workflow_dispatch:
  schedule:
    - cron: '40 22 * * *' # 每天 UTC 时间 0 点运行 (北京时间早上6点20)

permissions:
  contents: write

jobs:
  translate-files:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository on the same commit
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.workflow_run.head_sha }}
          fetch-depth: 0

      - name: Always copy specific root files
        run: |
          mkdir -p content/ja
          echo "Force copying specific files..."
          cp -vf content/cn/about.md content/ja/about.md || echo "Warning: content/cn/about.md not found."
          cp -vf content/cn/contact.md content/ja/contact.md || echo "Warning: content/cn/contact.md not found."
          cp -vf content/cn/privacy-policy.md content/ja/privacy-policy.md || echo "Warning: content/cn/privacy-policy.md not found."
          cp -vf content/cn/terms-of-service.md content/ja/terms-of-service.md || echo "Warning: content/cn/terms-of-service.md not found."

          echo "正在处理任意深度子目录下的 _index.md (不使用 nullglob)..."
          find content/cn/ -type f -name "_index.md" -print0 | while IFS= read -r -d $'\0' src_file; do
            # src_file 会是例如: content/cn/some/subdir/2025/_index.md
            # 这一步 find 已经确保了 src_file 是一个实际存在的文件，所以不需要额外的 -f 检查
            
            relative_path_to_cn_content="${src_file#content/cn/}" # 例如: some/subdir/2025/_index.md
            
            dest_file="content/ja/${relative_path_to_cn_content}"
            dest_dir=$(dirname "$dest_file")

            echo "找到源文件: $src_file"
            echo "目标路径: $dest_file"

            # 创建目标目录
            mkdir -p "$dest_dir"
            
            # 强制复制
            cp -vf "$src_file" "$dest_file" || echo "警告: 复制 $src_file 失败。"
          done
          

      - name: Sync other new files from cn to en and identify them
        id: sync_new_files
        run: |
          echo "Syncing other new files, ignoring existing ones..."
          rsync_output_file="rsync_created_files.txt"
          rsync -avi --ignore-existing --exclude 'about.md' content/cn/ content/ja/ | \
            grep '^>f\S* ' | awk '{print $2}' > "$rsync_output_file"
          echo "Rsync reported these new files (relative to content/ja/):"
          cat "$rsync_output_file"

      - name: Identify all files to translate
        id: find_changed_files
        run: |
          final_list_file="files_to_translate.txt"
          temp_list_file="temp_files_to_translate.txt"
          rsync_created_files="rsync_created_files.txt"
          en_dir="content/ja"
          > "$temp_list_file"
          if [ -f "$en_dir/_index.md" ]; then
            echo "$en_dir/_index.md" >> "$temp_list_file"
          fi
          if [ -f "$en_dir/about.md" ]; then
            echo "$en_dir/about.md" >> "$temp_list_file"
          fi
          if [ -f "$en_dir/contact.md" ]; then
            echo "$en_dir/contact.md" >> "$temp_list_file"
          fi
          if [ -f "$en_dir/privacy-policy.md" ]; then
            echo "$en_dir/privacy-policy.md" >> "$temp_list_file"
          fi
          if [ -f "$en_dir/terms-of-service.md" ]; then
            echo "$en_dir/terms-of-service.md" >> "$temp_list_file"
          fi
          if [ -s "$rsync_created_files" ]; then
            while IFS= read -r file_path; do
              echo "$en_dir/$file_path" >> "$temp_list_file"
            done < "$rsync_created_files"
          fi
          if [ -s "$temp_list_file" ]; then
            sort -u "$temp_list_file" > "$final_list_file"
          else
            > "$final_list_file"
          fi
          rm -f "$temp_list_file" "$rsync_created_files"
          if [ ! -s "$final_list_file" ]; then
            echo "No files identified for translation."
            echo "continue=false" >> $GITHUB_OUTPUT
          else
            echo "Found files to translate:"
            cat "$final_list_file"
            echo "continue=true" >> $GITHUB_OUTPUT
          fi

      - name: Set up Python and Install Dependencies
        if: steps.find_changed_files.outputs.continue == 'true'
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'
      - name: Install dependencies
        if: steps.find_changed_files.outputs.continue == 'true'
        run: pip install google-generativeai PyYAML

      - name: Translate changed files using Gemini
        if: steps.find_changed_files.outputs.continue == 'true'
        env:
          GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
        run: |
          import os
          import sys
          import re
          import yaml # For front matter processing
          import google.generativeai as genai

          # --- Helper function to strip basic Markdown/HTML for description ---
          def strip_markdown_html(text):
              # Remove HTML tags
              text = re.sub(r'<[^>]+>', '', text)
              # Remove Markdown images ![alt](src)
              text = re.sub(r'\!\[.*?\]\(.*?\)', '', text)
              # Replace Markdown links [text](url) with text (keeping the text)
              text = re.sub(r'\[(.*?)\]\(.*?\)', r'\1', text)
              # Remove Markdown heading lines themselves
              text = re.sub(r'(?m)^\s*#{1,6}\s+.*(\r?\n|$)', '', text)
              # Remove or replace other common Markdown structural/emphasis characters
              text = text.replace('**', '').replace('__', '') # Bold
              text = text.replace('*', '').replace('_', '')   # Italic / more bold
              text = re.sub(r'`(.*?)`', r'\1', text)          # Inline code to text
              # Remove blockquote markers, list markers at line start (EXCEPT numbered for new logic)
              text = re.sub(r'(?m)^\s*>\s?', '', text)
              text = re.sub(r'(?m)^\s*[\-\+\*]\s+', '', text) # Keep numbered for now, handle later if needed for general stripping
              # text = re.sub(r'(?m)^\s*\d+\.\s+', '', text) # Don't strip numbered list markers here
              # Remove horizontal rules
              text = re.sub(r'(?m)^\s*(\-\-\-|\*\*\*|\_\_\_)\s*$', '', text)
              # Normalize whitespace
              text = re.sub(r'\s+', ' ', text).strip()
              return text

          # --- Configure Gemini API ---
          try:
              genai.configure(api_key=os.environ["GEMINI_API_KEY"])
              model = genai.GenerativeModel('gemini-2.5-flash')
          except Exception as e:
              print(f"Error configuring Gemini API: {e}")
              sys.exit(1)

          # --- Translation function ---
          def translate_text(text_to_translate):
              if not text_to_translate.strip(): return ""
              prompt = f"""
                ### 角色：高级技术翻译与编辑

                你是一个为高标准技术出版物工作的翻译与编辑。你的工作有两个同样重要的部分：技术准确性和内容重构。任何一个部分的失败都意味着整个任务的失败。

                ---

                ### 第一步：执行“零容忍”规则 (Step 1: Execute the 'Zero-Tolerance' Rule)

                **这是你在处理文本时必须做的第一件事，先于所有其他编辑工作。此规则不容许任何失败。**

                *   **零容忍指令：强制翻译所有括号内的描述文本 `[ ]`**
                    *   **核心要求：** 你的首要扫描任务是找到文档中所有的Markdown链接 `[文本](URL)` 和图片 `![文本](URL)`。
                    *   **绝对规则:**
                        *   方括号 `[ ]` 内部的**所有中文描述文本** -> **必须无一例外地翻译成日文**。
                        *   圆括号 `( )` 内部的**所有URL或文件路径** -> **必须保持原样，绝不改动**。

                *   **强制自我审查 (Mandatory Self-Check):**
                    在生成最终回复之前，你必须在内部对自己提问并确认：
                    > **“我是否检查了最终文本中的每一个 `[` 和 `]`？是否所有中文描述都已被翻译，而所有URL都保持了原样？”**
                    >
                    如果答案是否定的，你的输出就是不合格的，必须修正。

                *   **范例：**
                    *   **原文:** `![AI构建模块优势](image.jpeg)`
                    *   **你的第一步处理结果:** `![翻译后的日文文本](image.jpeg)`

                ---

                ### 第二步：执行主要编辑任务 (Step 2: Execute the Primary Editorial Task)

                在完成了第一步的“零容忍”规则后，你现在可以对**正文段落**进行编辑。

                *   **主要编辑指令：强制性的“主题先行”重构**
                    *   对于每一个常规段落，识别其**核心主题**（如产品名、人名等）。
                    *   重写该段落，将这个**核心主题置于段落的最前方**，然后围绕它重新组织剩余信息。

                ---

                ### 第三步：应用一般风格指南 (Step 3: Apply General Style Guidelines)

                在完成以上两个核心步骤后，确保整体风格符合以下要求：

                *   **语气:** 对话式、非正式、有活力。
                *   **措辞:** 使用日常日文，可适度使用俚语。
                *   **Emoji:** 移除原文所有emoji，并根据日文语境策略性地添加新的。
                *   **格式:** 100%保留所有Markdown格式（标题、列表、代码块、`br`标签等）。
                *   **代码块:** 代码不译，注释要译。
                *   **完整性:** 翻译所有内容，保留段落结构。

                ---

                ### 第四步：最终输出 (Step 4: Final Output)

                *   **仅输出**最终编辑和翻译完成的日文文本。
                *   不要包含任何介绍、解释或你的思考过程。

                ---
                待翻译的中文文本：
                {text_to_translate}
                ---
                翻译后的日文文本：

              """
              try:
                  response = model.generate_content(prompt)
                  translated_content = ""
                  if response.parts:
                      for part in response.parts:
                          if hasattr(part, 'text'):
                              translated_content += part.text
                  else: # older versions might directly use response.text
                      translated_content = response.text if hasattr(response, 'text') else ''

                  # Handle potential API error structure where response.text might not exist but parts do.
                  # Also, ensure we don't fail if response or response.text is None.
                  if not translated_content and hasattr(response, 'prompt_feedback'):
                     print(f"Warning: Translation might have issues. Prompt feedback: {response.prompt_feedback}")
                     return "" # Or handle as error
                  
                  return translated_content.strip() if translated_content else ""

              except Exception as e:
                  print(f"An error occurred during translation: {e}")
                  if hasattr(e, 'response') and hasattr(e.response, 'prompt_feedback'):
                      print(f"Prompt Feedback: {e.response.prompt_feedback}")
                  return None

          # --- NEW: Load default description from hugo.yaml ---
          default_description_ja = None
          # Assuming hugo.yaml is in the script's working directory. Adjust path if necessary.
          hugo_config_path = 'hugo.yaml'
          try:
              with open(hugo_config_path, 'r', encoding='utf-8') as f:
                  hugo_config = yaml.safe_load(f)
                  # Safely access the nested key
                  if hugo_config and isinstance(hugo_config.get('params'), dict):
                      default_description_ja = hugo_config['params'].get('descriptionJA')
          
                  if default_description_ja:
                      print(f"Successfully loaded default description from {hugo_config_path}.")
                  else:
                      print(f"Warning: 'params.descriptionJA' key not found or is empty in {hugo_config_path}.")
          except FileNotFoundError:
              print(f"Warning: {hugo_config_path} not found. Cannot set default description for _index.md.")
          except yaml.YAMLError as ye:
              print(f"Warning: Error parsing {hugo_config_path}: {ye}. Cannot set default description.")
          except Exception as e:
              print(f"An unexpected error occurred while reading {hugo_config_path}: {e}")

          # --- Main processing loop ---
          with open('files_to_translate.txt', 'r', encoding='utf-8') as f:
              files_to_translate = [line.strip() for line in f if line.strip()]

          if not files_to_translate:
              print("No files listed in files_to_translate.txt. Exiting translation script.")
              sys.exit(0)

          for filepath in files_to_translate:
              print(f"Processing file: {filepath}")
              if not os.path.exists(filepath):
                  print(f"  - Warning: File {filepath} not found. Skipping.")
                  continue
              
              try:
                  with open(filepath, 'r', encoding='utf-8') as f:
                      content = f.read()
                  
                  parts = content.split('---', 2)
                  
                  if len(parts) == 3:
                      front_matter_str_content = parts[1]
                      body_to_translate = parts[2]
                      
                      parsed_fm = {}
                      fm_parse_success = False
                      if front_matter_str_content.strip():
                          try:
                              loaded_fm = yaml.safe_load(front_matter_str_content)
                              if isinstance(loaded_fm, dict):
                                  parsed_fm = loaded_fm
                                  fm_parse_success = True
                              else:
                                  print(f"  - Warning: Front matter in {filepath} is valid YAML but not a dictionary. FM modifications will be skipped.")
                          except yaml.YAMLError as ye:
                              print(f"  - Error parsing YAML front matter in {filepath}: {ye}. FM modifications will be skipped.")
                      else: # Empty front matter section (e.g. "--- \n ---")
                          fm_parse_success = True 

                      if not body_to_translate.strip():
                          print(f"  - Body of {filepath} is empty. Skipping translation, but will process front matter.")
                          translated_body = ""
                      else:
                          print("  - Translating body...")
                          translated_body = translate_text(body_to_translate)
                      
                      if translated_body is None:
                          print(f"  - Failed to translate body for file: {filepath}. Skipping update for this file.")
                          continue

                      # Requirement 1: Remove "---" from translated body content
                      if translated_body.strip().startswith("---"):
                          idx = translated_body.find("---")
                          translated_body = translated_body[idx + 3:].lstrip()
                      if translated_body.strip().endswith("---"):
                          idx = translated_body.rfind("---")
                          translated_body = translated_body[:idx].rstrip()

                      # --- Front Matter Modifications ---
                      if fm_parse_success:
                          base_fn = os.path.basename(filepath)
                          
                          # Requirement 2.1: Title update specific to date files
                          date_file_match = re.match(r"(\d{4})-(\d{2})-(\d{2})(?:[._-].*|\.md$)", base_fn)
                          if date_file_match:
                              year, month, day = date_file_match.groups() # Capture year, month, and day
                              print(f"  - Applying 'MM-DD-Daily' title rule for date file: {base_fn}")
                              parsed_fm['title'] = f"{month}-{day}-日报 AI 资讯日报" # Use month and day
                              parsed_fm['linkTitle'] = f"{month}-{day}-日报"
                          
                          # NEW: Update 'next' field for _index.md
                          if base_fn == "_index.md":
                              if 'next' in parsed_fm and isinstance(parsed_fm.get('next'), str):
                                  current_next_val = parsed_fm['next']
                                  if current_next_val and not current_next_val.startswith('/ja/'):
                                      # Prepend /ja, ensuring no double slashes if current_next_val starts with /
                                      if current_next_val.startswith('/'):
                                          parsed_fm['next'] = '/ja' + current_next_val
                                      else:
                                          parsed_fm['next'] = '/ja/' + current_next_val
                                      print(f"    - Updated 'next' field for _index.md to: {parsed_fm['next']}")
                                  elif not current_next_val:
                                      print(f"    - 'next' field in _index.md is empty. Not modifying.")
                                  else:
                                      print(f"    - 'next' field for _index.md already correctly prefixed or does not need update.")
                              else:
                                  print(f"    - 'next' field not found or not a string in _index.md front matter. Not modifying.")
                          
                          # Requirement 2.2: Description update
                          # NEW: Skip description update for about.md
                          if base_fn == "about.md":
                              print(f"  - Skipping description update for {base_fn}")
                          else:
                              print(f"  - Attempting to update description for: {base_fn} (from '1.' list item)")
                              description_content_found = False
                              # NEW: Regex to find the first numbered list item "1. " and capture its content
                              numbered_list_match = re.search(r"^\s*1\.\s+(.*)", translated_body, re.MULTILINE)

                              if base_fn == "_index.md":
                                    # 如果是 _index.md 文件，则使用默认的 description
                                    parsed_fm['description'] = default_description_ja
                                    description_content_found = True
                                    log_preview = default_description_ja[:50].replace('\n', ' ')
                                    print(f"    - Is _index.md, setting description to default: '{log_preview}...'")
                              else:
                                if numbered_list_match:
                                    text_from_list_item = numbered_list_match.group(1).strip()
                                    if text_from_list_item: # Ensure the item itself isn't empty after "1. "
                                        plain_text_for_desc = strip_markdown_html(text_from_list_item)
                                        new_description = plain_text_for_desc[:157] # Truncate for "..."
                                        if len(plain_text_for_desc) > 160:
                                            new_description += "."
                                        
                                        if new_description: # Only set description if plain_text_for_desc is not empty
                                            parsed_fm['description'] = new_description
                                            description_content_found = True
                                            log_description_preview = new_description[:50].replace('\n', ' ')
                                            print(f"    - Updated description from '1.' list item to: '{log_description_preview}...'")
                              
                              if not description_content_found:
                                  if 'description' in parsed_fm:
                                      # If _index.md specifically should have description: '', this handles it
                                      # if no content from "1." is found for it.
                                      parsed_fm['description'] = "" 
                                      print(f"    - No valid content from '1.' list item. Cleared/set existing description to empty for {base_fn}.")
                                  else:
                                      # If the file is _index.md and it didn't have a description key,
                                      # and we want to enforce description: '' as per example:
                                      if base_fn == "_index.md":
                                          parsed_fm['description'] = ""
                                          print(f"    - No valid content from '1.' list item. Set 'description: \"\"' for _index.md as per default.")
                                      else:
                                          print(f"    - No valid content from '1.' list item. 'description' key not present and not added for {base_fn}.") # Corrected variable base_fm to base_fn
                      # --- End of Front Matter Modifications ---

                      final_front_matter_str = ""
                      if fm_parse_success and parsed_fm: # Only dump if parsing was successful and there's data
                          try:
                              # Ensure no "---" inside FM values
                              for key, value in parsed_fm.items():
                                  if isinstance(value, str):
                                      parsed_fm[key] = value.replace('---', '') 
                              
                              final_front_matter_str = yaml.dump(
                                  parsed_fm, 
                                  sort_keys=False, 
                                  allow_unicode=True, 
                                  Dumper=yaml.SafeDumper,
                                  default_flow_style=False
                              ).strip()
                          except Exception as e_dump:
                              print(f"  - Error dumping YAML for {filepath}: {e_dump}. Using original front matter content if available.")
                              final_front_matter_str = front_matter_str_content.strip() # Fallback
                      elif front_matter_str_content.strip(): # FM parsing failed, but there was original FM
                           final_front_matter_str = front_matter_str_content.strip()
                      
                      # Assemble the new content
                      if not final_front_matter_str and not translated_body.strip():
                          new_content = "" # Completely empty file if nothing to write
                          print(f"  - Resulting file {filepath} would be empty. Writing empty file.")
                      elif not final_front_matter_str: # No front matter, only body
                          new_content = translated_body.lstrip()
                      elif not translated_body.strip(): # Front matter, but no body
                           new_content = f"---\n{final_front_matter_str}\n---"
                      else: # Both front matter and body exist
                           new_content = f"---\n{final_front_matter_str}\n---\n{translated_body.lstrip()}"


                      with open(filepath, 'w', encoding='utf-8') as f:
                          f.write(new_content)
                      print(f"  - Successfully translated and updated file: {filepath}")

                  else: # len(parts) != 3 (No valid Hugo front matter delimiter)
                      print(f"  - Could not find Hugo front matter delimiter (---) correctly in {filepath}. Attempting to translate whole file as body.")
                      # Fallback: Translate the whole content if no delimiters found
                      if not content.strip():
                          print(f"  - File {filepath} is empty. Skipping.")
                          continue

                      translated_whole_body = translate_text(content)
                      if translated_whole_body is None:
                          print(f"  - Failed to translate whole body for file: {filepath}. Skipping update.")
                          continue
                      
                      if translated_whole_body.strip().startswith("---"):
                          idx = translated_whole_body.find("---")
                          translated_whole_body = translated_whole_body[idx + 3:].lstrip()
                      if translated_whole_body.strip().endswith("---"):
                          idx = translated_whole_body.rfind("---")
                          translated_whole_body = translated_whole_body[:idx].rstrip()
                      with open(filepath, 'w', encoding='utf-8') as f:
                          f.write(translated_whole_body)
                      print(f"  - Successfully translated whole file (no front matter found): {filepath}")

              except Exception as e:
                  print(f"  - An error occurred while processing file {filepath}: {e}")
                  import traceback
                  traceback.print_exc()
        shell: python

      - name: Commit and push changes
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Actions Bot"
          git add content/ja/

          if git diff --staged --quiet; then
            echo "没有文件变更，无需提交。"
          else
            echo "检测到文件变更，正在提交..."
            git commit -m "chore(i18n): Auto-translate EN content with FM updates"
            git push
          fi 