"""
CRUD operations for form field management
"""

from typing import Dict, Any, Optional
from .base import FormFieldManagerBase
from ..models import Capture, Step, TallyfyError


class FormFieldCRUD(FormFieldManagerBase):
    """Handles basic CRUD operations for form fields"""

    def add_form_field_to_step(self, org_id: str, template_id: str, step_id: str, field_data: Dict[str, Any]) -> Optional[Capture]:
        """
        Add form fields (text, dropdown, date, etc.) to a step.
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            step_id: Step ID
            field_data: Form field creation data including field_type, label, required, etc.
            
        Returns:
            Created Capture object or None if creation failed
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        self._validate_step_id(step_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures"
            
            # Validate required fields
            required_fields = ['field_type', 'label']
            for field in required_fields:
                if field not in field_data:
                    raise ValueError(f"Missing required field: {field}")
            
            # Set defaults for optional fields
            capture_data = {
                'field_type': field_data['field_type'],
                'label': field_data['label'],
                'required': field_data.get('required', True),
                'position': field_data.get('position', 1)
            }
            
            # Add optional fields if provided
            optional_fields = [
                'guidance', 'options', 'default_value', 'default_value_enabled',
                'columns', 'collect_time', 'use_wysiwyg_editor',
                'field_validation', 'prefix', 'suffix', 'settings', 'list'
            ]
            for field in optional_fields:
                if field in field_data:
                    capture_data[field] = field_data[field]
            
            response_data = self.sdk._make_request('POST', endpoint, data=capture_data)
            
            extracted_data = self._extract_data(response_data)
            if extracted_data:
                return Capture.from_dict(extracted_data)
            else:
                self.sdk.logger.warning("Unexpected response format for form field creation")
                return None
                
        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "add form field to step", org_id=org_id, template_id=template_id, step_id=step_id)

    def update_form_field(self, org_id: str, template_id: str, step_id: str, field_id: str, **kwargs) -> Optional[Capture]:
        """
        Update form field properties, validation, options.
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            step_id: Step ID
            field_id: Form field ID
            **kwargs: Form field properties to update
            
        Returns:
            Updated Capture object or None if update failed
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        self._validate_step_id(step_id)
        self._validate_field_id(field_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures/{field_id}"
            
            # Build update data from kwargs
            update_data = {}
            allowed_fields = [
                'field_type', 'label', 'guidance', 'position', 'required',
                'options', 'default_value', 'default_value_enabled',
                'columns', 'collect_time', 'use_wysiwyg_editor',
                'field_validation', 'prefix', 'suffix', 'settings', 'list'
            ]
            
            for field, value in kwargs.items():
                if field in allowed_fields:
                    update_data[field] = value
                else:
                    self.sdk.logger.warning(f"Ignoring unknown form field: {field}")
            
            if not update_data:
                raise ValueError("No valid form field properties provided for update")
            
            response_data = self.sdk._make_request('PUT', endpoint, data=update_data)
            
            extracted_data = self._extract_data(response_data)
            if extracted_data:
                return Capture.from_dict(extracted_data)
            else:
                self.sdk.logger.warning("Unexpected response format for form field update")
                return None
                
        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "update form field", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)

    def move_form_field(self, org_id: str, template_id: str, from_step: str, field_id: str, to_step: str, position: int = 1) -> bool:
        """
        Move form field between steps.
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            from_step: Source step ID
            field_id: Form field ID to move
            to_step: Target step ID
            position: Position in target step (default: 1)
            
        Returns:
            True if move was successful
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        self._validate_step_id(from_step)
        self._validate_field_id(field_id)
        self._validate_step_id(to_step)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{from_step}/captures/{field_id}/move-out"

            move_data = {
                'target_step_id': to_step,
                'position': position
            }

            response_data = self.sdk._make_request('PUT', endpoint, data=move_data)

            # Verify the field actually landed on the target step
            extracted = self._extract_data(response_data)
            if isinstance(extracted, dict):
                # API returns the moved capture — check it references the target step
                moved_step = extracted.get('step_id') or extracted.get('target_step_id')
                if moved_step and str(moved_step) == str(to_step):
                    return True

            # Response didn't confirm the move; do a GET to verify
            verify_endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{to_step}"
            verify_response = self.sdk._make_request('GET', verify_endpoint)
            verify_data = self._extract_data(verify_response)
            if verify_data:
                captures = verify_data.get('captures', [])
                for capture in captures:
                    cap_id = capture.get('id') if isinstance(capture, dict) else None
                    if cap_id == field_id:
                        return True

            self.sdk.logger.warning(
                f"Move may have failed: field {field_id} not found on target step {to_step}"
            )
            return False
            
        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "move form field", org_id=org_id, template_id=template_id, from_step=from_step, field_id=field_id, to_step=to_step)

    def delete_form_field(self, org_id: str, template_id: str, step_id: str, field_id: str) -> bool:
        """
        Delete a form field from a step.
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            step_id: Step ID
            field_id: Form field ID
            
        Returns:
            True if deletion was successful
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        self._validate_step_id(step_id)
        self._validate_field_id(field_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures/{field_id}"
            
            self.sdk._make_request('DELETE', endpoint)
            return True
            
        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "delete form field", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)

    def reorder_form_fields(self, org_id: str, template_id: str, step_id: str,
                            field_order: list) -> bool:
        """
        Reorder form fields (captures) within a step.

        Args:
            org_id: Organization ID
            template_id: Template ID
            step_id: Step ID
            field_order: Ordered list of capture/field IDs in desired order

        Returns:
            True if reorder was successful

        Raises:
            TallyfyError: If the request fails
            ValueError: If field_order is not a valid list
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        self._validate_step_id(step_id)

        if not field_order or not isinstance(field_order, list):
            raise ValueError("field_order must be a non-empty list of field IDs")

        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures"
            # API processes one item at a time (StepCapturesReorderController.update)
            for item in field_order:
                body = {
                    'capture_id': item.get('capture_id') or item.get('id'),
                    'position': item['position'],
                }
                self.sdk._make_request('PUT', endpoint, data=body)
            return True

        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "reorder form fields", org_id=org_id, template_id=template_id, step_id=step_id)

    def get_step(self, org_id: str, template_id: str, step_id: str) -> Optional[Step]:
        """
        Get a specific step with its details.
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            step_id: Step ID
            
        Returns:
            Step object or None if not found
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        self._validate_step_id(step_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}"
            response_data = self.sdk._make_request('GET', endpoint)
            
            extracted_data = self._extract_data(response_data)
            if extracted_data:
                return Step.from_dict(extracted_data)
            else:
                self.sdk.logger.warning("Unexpected response format for step")
                return None
                
        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "get step", org_id=org_id, template_id=template_id, step_id=step_id)