import {
	Button,
	FormInputValidation,
	FormLabel,
	Gridicon,
	SegmentedControl,
} from '@automattic/components';
import { useTranslate } from 'i18n-calypso';
import { FunctionComponent, useState, FormEventHandler } from 'react';
import FormInputCheckbox from 'calypso/components/forms/form-checkbox';
import FormFieldset from 'calypso/components/forms/form-fieldset';
import FormPasswordInput from 'calypso/components/forms/form-password-input';
import FormSelect from 'calypso/components/forms/form-select';
import FormSettingExplanation from 'calypso/components/forms/form-setting-explanation';
import FormTextInput from 'calypso/components/forms/form-text-input';
import FormTextArea from 'calypso/components/forms/form-textarea';
import InfoPopover from 'calypso/components/info-popover';
import { useDispatch } from 'calypso/state';
import { recordTracksEvent } from 'calypso/state/analytics/actions';
import { FormState, FormMode, FormErrors, INITIAL_FORM_INTERACTION } from '../form';
import { getHostInfoFromId } from '../host-info';
import InlineInfo from './inline-info';
import './style.scss';

interface Props {
	formErrors: FormErrors;
	formMode: FormMode;
	formModeSwitcher?: 'segmented' | 'simple';
	disabled?: boolean;
	formState: FormState;
	onFormStateChange: ( newFormState: FormState ) => void;
	onModeChange: ( fromMode: FormMode ) => void;
	host: string;
	role: string;
	withHeader?: boolean;
	children?: React.ReactNode;
	allowFtp?: boolean;
}

const ServerCredentialsForm: FunctionComponent< Props > = ( {
	children,
	disabled = false,
	formState,
	formErrors,
	formMode,
	formModeSwitcher = 'segmented',
	onFormStateChange,
	onModeChange,
	host,
	role = 'main',
	withHeader = true,
	allowFtp = true,
} ) => {
	const translate = useTranslate();
	const dispatch = useDispatch();
	const [ interactions, setFormInteractions ] = useState( INITIAL_FORM_INTERACTION );
	const hostInfo = getHostInfoFromId( host );
	const isAlternate = role === 'alternate';
	formState.role = role;

	const handleFormChange: FormEventHandler< HTMLInputElement | HTMLSelectElement > = ( {
		currentTarget,
	} ) => {
		switch ( currentTarget.name ) {
			case 'protocol':
				onFormStateChange( {
					...formState,
					protocol: currentTarget.value as 'ftp' | 'ssh' | 'dynamic-ssh',
					port: ( () => {
						let port = parseInt( String( formState.port ) ) || 22;

						if ( formState.port === 22 && currentTarget.value === 'ftp' ) {
							port = 21;
						} else if ( formState.port === 21 && currentTarget.value === 'ssh' ) {
							port = 22;
						}

						return port;
					} )(),
				} );
				onModeChange( FormMode.Password );
				break;
			case 'host':
				setFormInteractions( { ...interactions, host: true } );
				onFormStateChange( { ...formState, host: currentTarget.value } );
				break;
			case 'site_url':
				setFormInteractions( { ...interactions, site_url: true } );
				onFormStateChange( { ...formState, site_url: currentTarget.value } );
				break;
			case 'port':
				setFormInteractions( { ...interactions, port: true } );
				onFormStateChange( {
					...formState,
					port: isNaN( parseInt( currentTarget.value ) ) ? '' : parseInt( currentTarget.value ),
				} );
				break;
			case 'user':
				setFormInteractions( { ...interactions, user: true } );
				onFormStateChange( { ...formState, user: currentTarget.value } );
				break;
			case 'pass':
				setFormInteractions( { ...interactions, pass: true } );
				onFormStateChange( { ...formState, pass: currentTarget.value } );
				break;
			case 'path':
				setFormInteractions( { ...interactions, path: true } );
				onFormStateChange( { ...formState, path: currentTarget.value } );
				break;
			case 'kpri':
				setFormInteractions( { ...interactions, kpri: true } );
				onFormStateChange( { ...formState, kpri: currentTarget.value } );
				break;
			case 'save_as_staging':
				setFormInteractions( { ...interactions, save_as_staging: true } );
				onFormStateChange( {
					...formState,
					save_as_staging: ( currentTarget as HTMLInputElement ).checked,
				} );
				break;
		}
	};

	const renderServerUsernameForm = () => (
		<FormFieldset className="credentials-form__username">
			<div className="credentials-form__support-info">
				<FormLabel htmlFor="server-username">{ translate( 'Username' ) }</FormLabel>
				{ hostInfo?.inline?.user && (
					<InfoPopover>
						<InlineInfo
							field="user"
							host={ host }
							info={ hostInfo.inline.user }
							protocol={ formState.protocol }
						/>
					</InfoPopover>
				) }
			</div>
			<FormTextInput
				name="user"
				id="server-username"
				placeholder={ translate( 'username' ) }
				value={ formState.user }
				onChange={ handleFormChange }
				disabled={ disabled }
				isError={ formErrors.user && ( interactions.user || ! formErrors.user.waitForInteraction ) }
				// Hint to LastPass not to attempt autofill
				data-lpignore="true"
			/>
			{ formErrors.user && ( interactions.user || ! formErrors.user.waitForInteraction ) && (
				<FormInputValidation isError text={ formErrors.user.message } />
			) }
		</FormFieldset>
	);

	const renderPasswordForm = () => (
		<div className="credentials-form__row credentials-form__user-pass">
			{ renderServerUsernameForm() }
			<FormFieldset className="credentials-form__password">
				<div className="credentials-form__support-info">
					<FormLabel htmlFor="server-password">{ translate( 'Password' ) }</FormLabel>
					{ hostInfo?.inline?.pass && (
						<InfoPopover>
							<InlineInfo
								field="pass"
								host={ host }
								info={ hostInfo.inline.pass }
								protocol={ formState.protocol }
							/>
						</InfoPopover>
					) }
				</div>
				<FormPasswordInput
					name="pass"
					id="server-password"
					placeholder={ translate( 'password' ) }
					value={ formState.pass }
					onChange={ handleFormChange }
					disabled={ disabled }
					isError={
						formErrors.pass && ( interactions.pass || ! formErrors.pass.waitForInteraction )
					}
					// Hint to LastPass not to attempt autofill
					data-lpignore="true"
				/>
				{ formErrors.pass && ( interactions.pass || ! formErrors.pass.waitForInteraction ) && (
					<FormInputValidation isError text={ formErrors.pass.message } />
				) }
			</FormFieldset>
		</div>
	);

	const renderPrivateKeyForm = () => (
		<>
			{ renderServerUsernameForm() }
			<FormFieldset className="credentials-form__kpri">
				<div className="credentials-form__support-info">
					<FormLabel htmlFor="private-key">{ translate( 'Private key' ) }</FormLabel>
					{ hostInfo?.inline?.kpri && (
						<InfoPopover>
							<InlineInfo
								field="kpri"
								host={ host }
								info={ hostInfo.inline.kpri }
								protocol={ formState.protocol }
							/>
						</InfoPopover>
					) }
				</div>
				<FormTextArea
					name="kpri"
					id="private-key"
					value={ formState.kpri }
					onChange={ handleFormChange }
					disabled={ disabled }
					className="credentials-form__private-key"
					isError={
						formErrors.kpri && ( interactions.kpri || ! formErrors.kpri.waitForInteraction )
					}
				/>
				{ formModeSwitcher === 'segmented' && (
					<FormSettingExplanation>
						{ translate( 'Only non-encrypted private keys are supported.' ) }
					</FormSettingExplanation>
				) }
				{ formErrors.kpri && ( interactions.kpri || ! formErrors.kpri.waitForInteraction ) && (
					<FormInputValidation isError text={ formErrors.kpri.message } />
				) }
			</FormFieldset>
		</>
	);

	const getSubHeaderText = () => {
		if ( isAlternate && hostInfo !== null && hostInfo.supportLink !== undefined ) {
			return translate(
				'Enter the server credentials from your hosting provider. {{a}}Learn how to find and enter your credentials{{/a}}',
				{
					components: {
						a: (
							<a
								target="_blank"
								rel="noopener noreferrer"
								href={ hostInfo.supportLink }
								onClick={ () =>
									dispatch(
										recordTracksEvent(
											'calypso_jetpack_advanced_credentials_flow_support_link_click',
											{ host }
										)
									)
								}
							/>
						),
					},
				}
			);
		} else if ( hostInfo !== null && hostInfo.inline !== undefined ) {
			return translate( 'Check the information icons for details on %(hostName)s', {
				args: {
					hostName: hostInfo?.name,
				},
			} );
		} else if ( hostInfo !== null && hostInfo.supportLink !== undefined ) {
			return 'generic' === host
				? translate(
						'Read through {{a}}our support site{{/a}} to learn how to obtain your credentials.',
						{
							components: {
								a: (
									<a
										target="_blank"
										rel="noopener noreferrer"
										href={ hostInfo.supportLink }
										onClick={ () =>
											dispatch(
												recordTracksEvent(
													'calypso_jetpack_advanced_credentials_flow_support_link_click',
													{ host }
												)
											)
										}
									/>
								),
							},
						}
				  )
				: translate(
						'Read through the {{a}}%(hostName)s support site{{/a}} to learn how to obtain your credentials.',
						{
							args: {
								hostName: hostInfo.name,
							},
							components: {
								a: (
									<a
										target="_blank"
										rel="noopener noreferrer"
										href={ hostInfo.supportLink }
										onClick={ () =>
											dispatch(
												recordTracksEvent(
													'calypso_jetpack_advanced_credentials_flow_support_link_click',
													{ host }
												)
											)
										}
									/>
								),
							},
						}
				  );
		}
		return translate( 'Your hosting provider will be able to supply this information to you.' );
	};

	const getFormHeaderText = () => {
		if ( ! allowFtp ) {
			return translate( 'Provide your SSH, SFTP server credentials' );
		}
		return translate( 'Provide your SSH, SFTP or FTP server credentials' );
	};

	const renderCredentialLinks = () => {
		if ( hostInfo !== null && hostInfo.credentialLinks !== undefined ) {
			if ( 'ftp' === formState.protocol && hostInfo.credentialLinks.ftp !== undefined ) {
				return (
					<Button
						className="credentials-form__credentials-guide-link"
						href={ hostInfo.credentialLinks.ftp }
						target="_blank"
						onClick={ () =>
							dispatch(
								recordTracksEvent(
									'calypso_jetpack_advanced_credentials_flow_credentials_guide_click',
									{
										host,
									}
								)
							)
						}
					>
						{ translate( 'Read the %(hostName)s credentials guide', {
							args: {
								hostName: hostInfo.name,
							},
						} ) }
						<Gridicon icon="external" />
					</Button>
				);
			}
			if ( 'ssh' === formState.protocol && hostInfo.credentialLinks.sftp !== undefined ) {
				return (
					<Button
						className="credentials-form__credentials-guide-link"
						href={ hostInfo.credentialLinks.sftp }
						target="_blank"
						onClick={ () =>
							dispatch(
								recordTracksEvent(
									'calypso_jetpack_advanced_credentials_flow_credentials_guide_click',
									{
										host,
									}
								)
							)
						}
					>
						{ translate( 'Read the %(hostName)s credentials guide', {
							args: {
								hostName: hostInfo.name,
							},
						} ) }
						<Gridicon icon="external" />
					</Button>
				);
			}
		}
		return null;
	};

	return (
		<div className="credentials-form">
			{ isAlternate && (
				<FormFieldset className="credentials-form__site-url">
					<div className="credentials-form__support-info">
						<FormLabel htmlFor="destination-url">{ translate( 'Destination URL' ) }</FormLabel>
					</div>
					<FormTextInput
						name="site_url"
						id="site-url"
						placeholder="https://example.com/"
						value={ formState.site_url }
						onChange={ handleFormChange }
						disabled={ disabled }
						isError={
							formErrors.site_url &&
							( interactions.site_url || ! formErrors.site_url.waitForInteraction )
						}
					/>
					{ formErrors.site_url &&
						( interactions.site_url || ! formErrors.site_url.waitForInteraction ) && (
							<FormInputValidation isError text={ formErrors.site_url.message } />
						) }
				</FormFieldset>
			) }
			{ ! isAlternate && withHeader && <h3>{ getFormHeaderText() }</h3> }
			{ withHeader && <p className="credentials-form__intro-text">{ getSubHeaderText() }</p> }
			{ withHeader && renderCredentialLinks() }
			{ ! allowFtp && <input type="hidden" name="protocol" value="ssh" /> }
			{ allowFtp && (
				<FormFieldset className="credentials-form__protocol-type">
					<div className="credentials-form__support-info">
						<FormLabel htmlFor="protocol-type">{ translate( 'Credential type' ) }</FormLabel>
						{ hostInfo?.inline?.protocol && (
							<InfoPopover>
								<InlineInfo
									field="protocol"
									host={ host }
									info={ hostInfo.inline.protocol }
									protocol={ formState.protocol }
								/>
							</InfoPopover>
						) }
					</div>
					<FormSelect
						name="protocol"
						id="protocol-type"
						value={ formState.protocol }
						onChange={ handleFormChange }
						disabled={ disabled }
					>
						<option value="ftp">{ translate( 'FTP' ) }</option>
						<option value="ssh">{ translate( 'SSH/SFTP' ) }</option>
					</FormSelect>
				</FormFieldset>
			) }
			<div className="credentials-form__row">
				<FormFieldset className="credentials-form__server-address">
					<div className="credentials-form__support-info">
						<FormLabel htmlFor="host-address">{ translate( 'Server address' ) }</FormLabel>
						{ hostInfo?.inline?.host && (
							<InfoPopover>
								<InlineInfo
									field="host"
									host={ host }
									info={ hostInfo.inline.host }
									protocol={ formState.protocol }
								/>
							</InfoPopover>
						) }
					</div>
					<FormTextInput
						name="host"
						id="host-address"
						placeholder={ translate( 'example.com' ) }
						value={ formState.host }
						onChange={ handleFormChange }
						disabled={ disabled }
						isError={
							formErrors.host && ( interactions.host || ! formErrors.host.waitForInteraction )
						}
					/>
					{ formErrors.host && ( interactions.host || ! formErrors.host.waitForInteraction ) && (
						<FormInputValidation isError text={ formErrors.host.message } />
					) }
				</FormFieldset>

				<FormFieldset className="credentials-form__port-number">
					<div className="credentials-form__support-info">
						<FormLabel htmlFor="server-port">{ translate( 'Port number' ) }</FormLabel>
						{ hostInfo?.inline?.port && (
							<InfoPopover>
								<InlineInfo
									field="port"
									host={ host }
									info={ hostInfo.inline.port }
									protocol={ formState.protocol }
								/>
							</InfoPopover>
						) }
					</div>
					<FormTextInput
						name="port"
						id="server-port"
						placeholder="22"
						value={ formState.port }
						onChange={ handleFormChange }
						disabled={ disabled }
						isError={
							formErrors.port && ( interactions.port || ! formErrors.port.waitForInteraction )
						}
					/>
					{ formErrors.port && ( interactions.port || ! formErrors.port.waitForInteraction ) && (
						<FormInputValidation isError text={ formErrors.port.message } />
					) }
				</FormFieldset>
			</div>
			<FormFieldset className="credentials-form__path">
				<div className="credentials-form__support-info">
					<FormLabel htmlFor="wordpress-path">
						{ translate( 'WordPress installation path' ) }
					</FormLabel>
					{ hostInfo?.inline?.path && (
						<InfoPopover>
							<InlineInfo
								field="path"
								host={ host }
								info={ hostInfo.inline.path }
								protocol={ formState.protocol }
							/>
						</InfoPopover>
					) }
				</div>
				<FormTextInput
					name="path"
					id="wordpress-path"
					placeholder="/public_html/wordpress-site/"
					value={ formState.path }
					onChange={ handleFormChange }
					disabled={ disabled }
					isError={
						formErrors.path && ( interactions.path || ! formErrors.path.waitForInteraction )
					}
				/>
				{ formErrors.path && ( interactions.path || ! formErrors.path.waitForInteraction ) && (
					<FormInputValidation isError text={ formErrors.path.message } />
				) }
			</FormFieldset>
			{ formModeSwitcher === 'segmented' && 'ftp' !== formState.protocol && (
				<div className="credentials-form__mode-control">
					<div className="credentials-form__support-info">
						<SegmentedControl disabled={ disabled }>
							<SegmentedControl.Item
								selected={ formMode === FormMode.Password }
								onClick={ () => onModeChange( FormMode.Password ) }
							>
								{ translate( 'Use password' ) }
							</SegmentedControl.Item>
							<SegmentedControl.Item
								selected={ formMode === FormMode.PrivateKey }
								onClick={ () => onModeChange( FormMode.PrivateKey ) }
							>
								{ translate( 'Use private key' ) }
							</SegmentedControl.Item>
						</SegmentedControl>
						{ hostInfo?.inline?.mode && (
							<InfoPopover>
								<InlineInfo
									field="mode"
									host={ host }
									info={ hostInfo.inline.mode }
									protocol={ formState.protocol }
								/>
							</InfoPopover>
						) }
					</div>
				</div>
			) }
			{ formModeSwitcher === 'simple' && (
				<FormFieldset>
					<FormLabel>{ translate( 'SSH credentials' ) }</FormLabel>
					<FormSettingExplanation>
						{ translate(
							'Your credentials will be used only to migrate the site and won’t be stored anywhere.'
						) }
					</FormSettingExplanation>
				</FormFieldset>
			) }
			{ formMode === FormMode.Password ? renderPasswordForm() : renderPrivateKeyForm() }
			{ formModeSwitcher === 'simple' && (
				<>
					{ formMode === FormMode.Password && (
						<p>
							<Button plain onClick={ () => onModeChange( FormMode.PrivateKey ) }>
								{ translate( 'Use private key instead' ) }
							</Button>
						</p>
					) }
					{ formMode === FormMode.PrivateKey && (
						<p>
							<span>{ translate( 'Only non-encrypted private keys are supported.' ) }</span>{ ' ' }
							<Button plain onClick={ () => onModeChange( FormMode.Password ) }>
								{ translate( 'Use a password instead' ) }
							</Button>
						</p>
					) }
				</>
			) }
			{ isAlternate && (
				<FormFieldset className="credentials-form__save-for-later">
					<FormLabel htmlFor="save-for-later">
						<FormInputCheckbox
							checked={ formState.save_as_staging }
							id="save-for-later"
							name="save_as_staging"
							onChange={ handleFormChange }
							value="true"
						/>
						<span>
							{ translate( 'Remember credentials' ) }
							<InfoPopover
								className="credentials-form__remember-credentials-info-popover"
								position="right"
								showOnHover
							>
								{ translate(
									'Save this configuration so you can easily access it the next time you copy a site to staging.'
								) }
							</InfoPopover>
						</span>
					</FormLabel>
				</FormFieldset>
			) }
			<FormFieldset className="credentials-form__buttons">
				<div className="credentials-form__buttons-flex">{ children }</div>
			</FormFieldset>
		</div>
	);
};

export default ServerCredentialsForm;
